|
Occasionally the programmer will want to return simply undef or an empty list
if a function fails rather than a separate status value. The rpcb_gettime() function offers
just this situation. If the function succeeds we would like to have it return the time and if
it fails we would like to have undef returned. In the following Perl code the value of $timep
will either be undef or it will be a valid time.
$timep = rpcb_gettime( "localhost" );
|
|
The following XSUB uses the SV * return type as a mnemonic only, and uses a
CODE: block to indicate to the compiler that the programmer has supplied all the necessary
code. The sv_newmortal() call will initialize the return value to undef, making that the
default return value.
SV *
rpcb_gettime(host)
char * host
PREINIT:
time_t timep;
bool_t x;
CODE:
ST(0) = sv_newmortal();
if( rpcb_gettime( host, &timep ) )
sv_setnv( ST(0), (double)timep);
|
|
The next example demonstrates how one would place an explicit undef in the return value,
should the need arise.
SV *
rpcb_gettime(host)
char * host
PREINIT:
time_t timep;
bool_t x;
CODE:
ST(0) = sv_newmortal();
if( rpcb_gettime( host, &timep ) ){
sv_setnv( ST(0), (double)timep);
}
else{
ST(0) = &PL_sv_undef;
}
|
|
To return an empty list one must use a PPCODE: block and then not push return values on the
stack.
void
rpcb_gettime(host)
char *host
PREINIT:
time_t timep;
PPCODE:
if( rpcb_gettime( host, &timep ) )
PUSHs(sv_2mortal(newSViv(timep)));
else{
/* Nothing pushed on stack, so an empty
* list is implicitly returned. */
}
|
|
Some people may be inclined to include an explicit return in the above XSUB,
rather than letting control fall through to the end. In those situations XSRETURN_EMPTY
should be used, instead. This will ensure that the XSUB stack is properly adjusted. Consult perlguts/"API LISTING" for other XSRETURN
macros.
Since XSRETURN_* macros can be used with CODE blocks as well, one can rewrite
this example as:
int
rpcb_gettime(host)
char *host
PREINIT:
time_t timep;
CODE:
RETVAL = rpcb_gettime( host, &timep );
if (RETVAL == 0)
XSRETURN_UNDEF;
OUTPUT:
RETVAL
|
|
In fact, one can put this check into a POSTCALL: section as well. Together with PREINIT:
simplifications, this leads to:
int
rpcb_gettime(host)
char *host
time_t timep;
POSTCALL:
if (RETVAL == 0)
XSRETURN_UNDEF;
|
|
|
|