The rules of using the varargs macros dictate that either:
- The first argument tells you how many arguments are passed.
- Or the last argument passed is some kind of sentinal value that tell you when you have that last argument.
Here's an example of using the latter:
#! perl -slw
use strict;
use Inline C => <<'END_C', NAME => 'varArgsC2P', CLEAN_AFTER_BUILD =>
+ 0;
void foo (int first, ...) {
dSP ;
int next;
va_list argp;
ENTER ;
SAVETMPS ;
PUSHMARK(SP) ;
va_start( argp, first );
XPUSHs( sv_2mortal( newSViv( first ) ) );
while( ( next = va_arg( argp, int ) ) != -1 ) {
XPUSHs( sv_2mortal( newSViv( next ) ) );
// printf( "Stacking %d \n", next );
}
va_end( argp );
PUTBACK;
perl_call_pv( "main::test", G_SCALAR );
// SPAGAIN;
FREETMPS;
LEAVE;
}
void call_foo( int n ) {
switch( n ) {
case 1: foo( 1, -1 ); break;
case 2: foo( 1,2, -1 ); break;
case 3: foo( 1,2,3, -1 ); break;
case 4: foo( 1,2,3,4, -1 ); break;
case 5: foo( 1,2,3,4,5, -1 ); break;
case 6: foo( 1,2,3,4,5,6, -1 ); break;
case 7: foo( 1,2,3,4,5,6,7, -1 ); break;
case 8: foo( 1,2,3,4,5,6,7,8, -1 ); break;
case 9: foo( 1,2,3,4,5,6,7,8,9, -1 ); break;
case 10: foo( 1,2,3,4,5,6,7,8,9,10, -1 ); break;
}
return;
}
END_C
sub test {
printf "test called with %d args: [@_]\n", scalar @_;
}
call_foo( $_ ) for 1 .. 10;
__END__
C:\test>varArgsC2P.pl
test called with 1 args: [1]
test called with 2 args: [1 2]
test called with 3 args: [1 2 3]
test called with 4 args: [1 2 3 4]
test called with 5 args: [1 2 3 4 5]
test called with 6 args: [1 2 3 4 5 6]
test called with 7 args: [1 2 3 4 5 6 7]
test called with 8 args: [1 2 3 4 5 6 7 8]
test called with 9 args: [1 2 3 4 5 6 7 8 9]
test called with 10 args: [1 2 3 4 5 6 7 8 9 10]
Note that I'm calling call_foo( n ) from Perl, so that C can callback to main::test with the specified number of arguments.
Note also that you can only use the sentinal value method if a) all the arguments are of the same type--you have to call the va_arg() macro with the appropriate (hardcoded) type; b) if there is a suitable sentinal value.
Finally, I'm not sure whether the SPAGAIN macro should be called. Some examples show it, but I've never found an explanation of what it does or when/why you should call it. The code seems to work with and without it.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
|