为什么在XSUB中包含输出变量的SvSETMAGIC()?

Håk*_*and 9 perl xs

阅读perlxs文档,我来到了OUTPUT关键字的部分:

xsubppSvSETMAGIC()为XSUB的OUTPUT部分中的所有参数发出自动,RETVAL除外.这是通常需要的行为,因为它负责在输出参数上正确调用'set'魔术(如果它们不存在则必须创建的哈希或数组元素参数需要).

我不确定我理解为什么需要set魔法(以及为什么不需要魔法RETVAL)?为什么set哈希和数组元素参数需要魔术?

not*_*uch 6

所有Perl的数据结构都支持魔术,而不仅仅是SVs(尽管名称),特别是对于哈希和数组,这是诸如在哈希条目级别实现弱引用模拟的tie机制或类似事物的基础fieldhash.

由于该OUTPUT指令指示哪些参数可能会被XSUB的C主体修改,并且可能传入包含set magic的变量,因此根据typemap设置该值而不调用set handler可能会导致行为不一致.

use Scalar::Util qw(weaken);

my $foo;
my $ref = \$foo;
weaken($ref);
Run Code Online (Sandbox Code Playgroud)

作为魔法的一个例子,weaken递减引用计数$foo,并添加魔法指向回来,$ref以便在$foo收集垃圾时将其清除.

此外,它还添加了设置魔法$ref,以拆除这种反向引用,否则当$foo被破坏时,$ref即使在此时它不再指向,也会被清除$foo.

如果你使用$ ref作为参数,它会在堆栈上出现别名(这就是为什么$_[0]可以赋值):

modifies_arguments($ref);

sub modifies_arguments {
    $_[0] = "blah"; # set magic is invoked to tear down the back referencing
} 
Run Code Online (Sandbox Code Playgroud)

如果modifies_arguments是一个纯粹的Perl,很容易理解为什么这是合适的,但是关于正确性的相同假设当然必须适用于XSUB,这就是为什么OUTPUT用于标记哪些参数的值设置为C级参数变量所具有的值.函数体的结束,并设置了魔法触发.

这不适用于RETVAL,因为这在技术上不是一个赋值,而是将一个新的SV推入堆栈,并且在函数返回赋值操作(如果有的话)之后将处理任何设置魔法.