How to emulate and call a call from XS?
How to emulate sub behavior z
in XS
sub?
package XS;
sub hello {
print "ARGS: >>@_<<\n";
my $lvl;
while( my @frame = caller( $lvl++ ) ) {
print ">>@frame[0..4]<<\n";
}
}
sub z {
&hello;
}
In my file .xs
I have:
void
call_perl() {
call_pv( "XS::hello", G_NOARGS );
}
void
test(...)
CODE:
call_perl();
But the call XS::test(1,2,3)
does not pass any arguments to hello
.
Output:
ARGS: >><<
>>main -e 1 XS::hello <<
Here we see that the flag is $hasargs
not set because of the flag G_NOARG
, but why @_
is it cleared? What did I miss?
UPD
Seems to have found half the answer.
G_NOARGS flag
affects the creation of the @_ array for the Perl routine.
When
XSUB
called perl, do not create a frame for it (do not remember where it is described) and do not fill in@_
for it (it is described indirectly here )XSUB reference their stack arguments with the ST (x) macro
, :
XSUB
PP
?
: :
call_pv( "XS::hello", 0 );
PP. XSUB
, XS::hello
sub
int count = call_pv( "XS::hello", 0 );
STAGAIN;
printf( "%s\n", SvPV_nolen( ST(0) ) );
, G_NOARGS
, XSUB
PP
sub
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 @_