Nick Ing-Simmons wrote:

Steve Hay <[EMAIL PROTECTED]> writes:


I have an XSUB that calls a C function to get three integers, and then returns them (in list context). In scalar context it just returns a Boolean to indicate whether the C function succeeded or not. It currently looks like this:

void
my_func()
 PREINIT:
     I32     gimme;
     int     one, two, three;

 PPCODE:
     gimme = GIMME_V;
     if (My_Func(&one, &two, &three) == 0) {
         if (gimme == G_SCALAR) {
             XSRETURN_YES;
         }
         else if (gimme == G_ARRAY) {
             EXTEND(SP, 3);
             PUSHs(sv_2mortal(newSViv(one)));
             PUSHs(sv_2mortal(newSViv(two)));
             PUSHs(sv_2mortal(newSViv(three)));
         }
     }
     else {
         if (gimme == G_SCALAR)
             XSRETURN_NO;
         else if (gimme == G_ARRAY)
             XSRETURN_EMPTY;
     }

I have a few questions about this:
[snip]


- Are the XSRETURN_* macros OK in a PPCODE section?


PPCODE sections normally PUSHs their args onto a perl stack which has been unwound to point at ST(0) slot. It is possible that XSRETURN_NO/XSRETURN_YES might be confused by that.
You could use a CODE: version as you know the return counts in advance.




The Perl manpages seem to say it's OK, but I read something somewhere (can't remember where) that it wasn't a good idea because the C code generated contains "return" statements in a void() subroutine.



All XSes are void subroutines.


XSRETURN_XXXX just do various perl-stack twiddling then "return" in C.

void
my_func()
CODE:
{
I32 gimme = GIMME_V;
int one, two, three;
if (My_Func(&one, &two, &three) == 0) {
if (gimme == G_SCALAR) {
XSRETURN_YES;
}
else if (gimme == G_ARRAY) {
EXTEND(SP, 3);
ST(0) = sv_2mortal(newSViv(one));
ST(1) = sv_2mortal(newSViv(two));
ST(2) = sv_2mortal(newSViv(three));
XSRETURN(3);
}
else {
XSRETURN_EMPTY;
}
}
else {
if (gimme == G_SCALAR)
XSRETURN_NO;
else
XSRETURN_EMPTY;
}
}


I had looked at using a CODE: section before, but two things in the perlxs manpage put me off:

In the section on PPCODE it says:

"Occasionally one will want an XSUB to return a list of values rather than a single value. In these cases one must use PPCODE: and then explicitly push the list of values on the stack."

Why does it say that you _must_ use PPCODE if CODE is actually OK? Is that a documentation error?

Also, in the section on RETVAL it says:

"If PPCODE: directive is not used, void return value should be used only for subroutines which do not return a value, even if CODE: directive is used which sets ST(0) explicitly."

This also instructs me not to use CODE since my XSUB declaration is "void".

So it seems there are problems using PPCODE or CODE, which leaves me rather confused. Which is the lesser of the two evils?

Either version of the simple XSUB above works fine, but I just wanted to try and get things straight in my mind before I move onto bigger XSUBs in the future.

- Steve



Reply via email to