2016-12-15 6 views
9

Чтение perlxs documentation, я пришел в секцию по OUTPUT ключевому слову:Зачем включать SvSETMAGIC() в выходные переменные в XSUB?

xsubpp излучает автоматический SvSETMAGIC() для всех параметров в разделе OUTPUT на XSub, кроме RETVAL. Это обычно требуется поведение , так как он заботится о правильном вызове магии «set» на выходных параметрах (необходимые для параметров элемента hash или массива, которые должны быть созданы, если они не существовали).

Я не уверен, я понимаю, почему желательно set магии (и почему это не требуется для RETVAL)? И почему set магия необходима для хэша и параметров элемента массива?

ответ

6

Все структуры данных в Perl поддержки магии, а не только SV s (несмотря на название) и специально для хэшей и массивов это является основой для вещей, как tie механизм или тому подобное fieldhash, который реализует аналог слабых литературы в уровень хэш-записей.

Поскольку директива OUTPUT указывает, какие аргументы, по-видимому, будут изменены корпусом C XSUB, и переменная, содержащая заданную магию, может быть передана, установка значения в соответствии с типовой картой без вызова обработчика набора может привести к непоследовательности поведение.

use Scalar::Util qw(weaken); 

my $foo; 
my $ref = \$foo; 
weaken($ref); 

В качестве примера магии, weaken вычитает счетчик ссылок $foo, и добавляет магию указывая обратно $ref так, что он очищается, когда $foo получает мусора.

Кроме того, он также добавляет набор магии $ref, чтобы разрушить эту спину, ссылающийся, в противном случае, когда $foo разрушается, $ref не будет очищен, даже если в данный момент он уже не указывает на $foo.

Если вы используете $ реф в качестве аргумента, он получает псевдонимы в стеке (поэтому $_[0] is assignable):

modifies_arguments($ref); 

sub modifies_arguments { 
    $_[0] = "blah"; # set magic is invoked to tear down the back referencing 
} 

Если modifies_arguments является чистым Perl это легко понять, почему это необходимо, но Разумеется, те же предположения о правильности должны иметь место для XSUB, поэтому OUTPUT используется, чтобы отметить, какие аргументы будут иметь свое значение, установленное в значение переменной аргумента уровня C в конце тела функции, и установили срабатывание магии.

Это не относится к RETVAL, так как это не технически назначение, а скорее толкание нового SV в стек, и любое заданное волшебство будет обработано после возвращения функции по присваиванию op (если оно есть).

+0

Спасибо за разъяснение этого! Как насчет цитированного текста в скобках: * '", необходимых для параметров хэша или элемента массива, которые должны быть созданы, если они не существовали "' *? Что это значит? Означает ли это, что маска 'set' не применяется к скалярам или чему-то еще? –

+0

'my @array; modifies_arguments ($ array [42]) 'будет только создавать элемент массива, когда он фактически изменен, ср. autovivification. Если массив магический, то это будет включать в себя набор магии на самом массиве. Тем не менее, это относится и к скалярам, ​​как в приведенном выше примере $ ref. – nothingmuch

2

Это довольно просто. Всякий раз, когда вы назначаете скаляр, вам нужно называть его SvSETMAGIC(), если у него есть волшебство, связанное с ним.

Присвоение RETVAL не присваивается переменной Perl, поэтому вызов SvSETMAGIC(RETVAL) (если вы фактически не изменили RETVAL) был бы неправильным.Если возвращаемое значение присваивается другому скаляру в вызывающем объекте, то присваивание вызовет SvGETMAGIC по возвращаемому значению перед назначением и SvSETMAGIC по назначенной переменной после назначения.