Как эмулировать вызов &sname из XS?
Как подражать z
суб поведение внутри XS
к югу?
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
Кажется, нашел половину ответа.
Флаг G_NOARGS
имеет эффект не создания массива @_ для подпрограммы Perl.
когда
XSUB
называется perl, не создайте для него рамку (не помню, где это описано) и не заполняйте@_
для этого (это описано здесь косвенно)XSUB ссылаются на свои аргументы стека с помощью макроса ST(x)
Так что более точный вопрос будет:
Как размножаться XSUB
складывать аргументы в PP
подпрограмма?
ВНИМАНИЕ: я не могу просто использовать:
call_pv( "XS::hello", 0 );
Потому что это порядковый PP суб-вызов. И когда он возвращает XSUB
аргументы стека будут заменены возвращаемым значением из XS::hello
суб
int count = call_pv( "XS::hello", 0 );
STAGAIN;
printf( "%s\n", SvPV_nolen( ST(0) ) );
Поэтому я поставляю G_NOARGS
флаг, чтобы иметь возможность доступа XSUB
стек аргументов после вызова PP
суб
1 ответ
Вот код для 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 @_