如何模拟 XS的调用?



如何在XS子中模拟z子行为?

package XS;
sub hello {
print "ARGS: >>@_<<n";
my $lvl;
while( my @frame =  caller( $lvl++ ) ) {
print ">>@frame[0..4]<<n";
}
}
sub z {
&hello;
}

在我的.xs文件中,我有:

void
call_perl() {
call_pv( "XS::hello", G_NOARGS );    
}
void
test(...)
CODE:
call_perl();

但是调用XS::test(1,2,3)不会将任何参数传递给hello.

输出:

ARGS: >><<
>>main -e 1 XS::hello <<

这里我们可以看到$hasargs标志不是因为G_NOARG标志而设置的,但是为什么@_被刷新了呢?我错过了什么?

UPD
似乎找到了一半的答案。

  1. G_NOARGS旗

    具有不为 Perl 子例程创建 @_ 数组的效果。

  2. XSUB被称为perl时,不要为它创建框架(不记得在哪里描述),也不为它填充@_(这里间接描述)

    XSUB 使用宏 ST(x) 引用它们的堆栈参数

所以更精确的问题是:

如何将XSUB堆栈参数传播到PP子例程?

注意:我不能只使用:

call_pv( "XS::hello", 0 );

因为这是序号PP子调用。当它返回时,XSUB堆栈参数将被来自 sub 的返回值替换XS::hello

int count =  call_pv( "XS::hello", 0 );
STAGAIN;
printf( "%sn", SvPV_nolen( ST(0) ) );

所以我提供了G_NOARGS标志,以便能够在调用 sub 后访问XSUB堆栈参数PP

这是XSUB如何完成的代码(注意:在这个例子中我不处理返回参数):

test(...)
CODE:
AV *defav_old =  GvAV(PL_defgv);   # Save current @_
AV *av = newAV();                  # Create new array
av_extend(av, items -1);          
AvREIFY_only(av);
AvFILLp(av) =  items -1;
Copy(MARK+1, AvARRAY(av), items, SV*); # Fill array by elements from stack
GvAV(PL_defgv) =  av;     # point @_ to our new array

PUSHMARK(SP);
int count =  call_pv( "XS::Utils::hello", G_VOID | G_NOARGS );
GvAV(PL_defgv) =  defav_old;  # Restore old @_

相关内容

  • 没有找到相关文章

最新更新