|
The PPCODE: keyword is an alternate form of the CODE: keyword and is used to tell the xsubpp
compiler that the programmer is supplying the code to control the argument stack for the XSUBs
return values. 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. The PPCODE: and CODE: keywords should not be used together within the same XSUB.
The actual difference between PPCODE: and CODE: sections is in the initialization of SP
macro (which stands for the current Perl stack pointer), and in the handling of data on
the stack when returning from an XSUB. In CODE: sections SP preserves the value which was on
entry to the XSUB: SP is on the function pointer (which follows the last parameter). In PPCODE:
sections SP is moved backward to the beginning of the parameter list, which allows PUSH*()
macros to place output values in the place Perl expects them to be when the XSUB returns back
to Perl.
The generated trailer for a CODE: section ensures that the number of return values Perl
will see is either 0 or 1 (depending on the voidness of the return value of the C
function, and heuristics mentioned in "The RETVAL
Variable"). The trailer generated for a PPCODE: section is based on the number of
return values and on the number of times SP was updated by [X]PUSH*()
macros.
Note that macros ST(i), XST_m*() and XSRETURN*()
work equally well in CODE: sections and PPCODE: sections.
The following XSUB will call the C rpcb_gettime() function and will return its two output
values, timep and status, to Perl as a single list.
void
rpcb_gettime(host)
char *host
PREINIT:
time_t timep;
bool_t status;
PPCODE:
status = rpcb_gettime( host, &timep );
EXTEND(SP, 2);
PUSHs(sv_2mortal(newSViv(status)));
PUSHs(sv_2mortal(newSViv(timep)));
|
|
Notice that the programmer must supply the C code necessary to have the real rpcb_gettime()
function called and to have the return values properly placed on the argument stack.
The void return type for this function tells the xsubpp compiler that
the RETVAL variable is not needed or used and that it should not be created. In most scenarios
the void return type should be used with the PPCODE: directive.
The EXTEND() macro is used to make room on the argument stack for 2 return values. The
PPCODE: directive causes the xsubpp compiler to create a stack pointer available as SP,
and it is this pointer which is being used in the EXTEND() macro. The values are then pushed
onto the stack with the PUSHs() macro.
Now the rpcb_gettime() function can be used from Perl with the following statement.
($status, $timep) = rpcb_gettime("localhost");
|
|
When handling output parameters with a PPCODE section, be sure to handle 'set' magic
properly. See perlguts for
details about 'set' magic.
|