mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1352 lines
45 KiB
1352 lines
45 KiB
=head1 NAME
|
|
|
|
perlxs - XS language reference manual
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
=head2 Introduction
|
|
|
|
XS is a language used to create an extension interface
|
|
between Perl and some C library which one wishes to use with
|
|
Perl. The XS interface is combined with the library to
|
|
create a new library which can be linked to Perl. An B<XSUB>
|
|
is a function in the XS language and is the core component
|
|
of the Perl application interface.
|
|
|
|
The XS compiler is called B<xsubpp>. This compiler will embed
|
|
the constructs necessary to let an XSUB, which is really a C
|
|
function in disguise, manipulate Perl values and creates the
|
|
glue necessary to let Perl access the XSUB. The compiler
|
|
uses B<typemaps> to determine how to map C function parameters
|
|
and variables to Perl values. The default typemap handles
|
|
many common C types. A supplement typemap must be created
|
|
to handle special structures and types for the library being
|
|
linked.
|
|
|
|
See L<perlxstut> for a tutorial on the whole extension creation process.
|
|
|
|
Note: For many extensions, Dave Beazley's SWIG system provides a
|
|
significantly more convenient mechanism for creating the XS glue
|
|
code. See L<http://www.cs.utah.edu/~beazley/SWIG> for more
|
|
information.
|
|
|
|
=head2 On The Road
|
|
|
|
Many of the examples which follow will concentrate on creating an interface
|
|
between Perl and the ONC+ RPC bind library functions. The rpcb_gettime()
|
|
function is used to demonstrate many features of the XS language. This
|
|
function has two parameters; the first is an input parameter and the second
|
|
is an output parameter. The function also returns a status value.
|
|
|
|
bool_t rpcb_gettime(const char *host, time_t *timep);
|
|
|
|
From C this function will be called with the following
|
|
statements.
|
|
|
|
#include <rpc/rpc.h>
|
|
bool_t status;
|
|
time_t timep;
|
|
status = rpcb_gettime( "localhost", &timep );
|
|
|
|
If an XSUB is created to offer a direct translation between this function
|
|
and Perl, then this XSUB will be used from Perl with the following code.
|
|
The $status and $timep variables will contain the output of the function.
|
|
|
|
use RPC;
|
|
$status = rpcb_gettime( "localhost", $timep );
|
|
|
|
The following XS file shows an XS subroutine, or XSUB, which
|
|
demonstrates one possible interface to the rpcb_gettime()
|
|
function. This XSUB represents a direct translation between
|
|
C and Perl and so preserves the interface even from Perl.
|
|
This XSUB will be invoked from Perl with the usage shown
|
|
above. Note that the first three #include statements, for
|
|
C<EXTERN.h>, C<perl.h>, and C<XSUB.h>, will always be present at the
|
|
beginning of an XS file. This approach and others will be
|
|
expanded later in this document.
|
|
|
|
#include "EXTERN.h"
|
|
#include "perl.h"
|
|
#include "XSUB.h"
|
|
#include <rpc/rpc.h>
|
|
|
|
MODULE = RPC PACKAGE = RPC
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep
|
|
OUTPUT:
|
|
timep
|
|
|
|
Any extension to Perl, including those containing XSUBs,
|
|
should have a Perl module to serve as the bootstrap which
|
|
pulls the extension into Perl. This module will export the
|
|
extension's functions and variables to the Perl program and
|
|
will cause the extension's XSUBs to be linked into Perl.
|
|
The following module will be used for most of the examples
|
|
in this document and should be used from Perl with the C<use>
|
|
command as shown earlier. Perl modules are explained in
|
|
more detail later in this document.
|
|
|
|
package RPC;
|
|
|
|
require Exporter;
|
|
require DynaLoader;
|
|
@ISA = qw(Exporter DynaLoader);
|
|
@EXPORT = qw( rpcb_gettime );
|
|
|
|
bootstrap RPC;
|
|
1;
|
|
|
|
Throughout this document a variety of interfaces to the rpcb_gettime()
|
|
XSUB will be explored. The XSUBs will take their parameters in different
|
|
orders or will take different numbers of parameters. In each case the
|
|
XSUB is an abstraction between Perl and the real C rpcb_gettime()
|
|
function, and the XSUB must always ensure that the real rpcb_gettime()
|
|
function is called with the correct parameters. This abstraction will
|
|
allow the programmer to create a more Perl-like interface to the C
|
|
function.
|
|
|
|
=head2 The Anatomy of an XSUB
|
|
|
|
The following XSUB allows a Perl program to access a C library function
|
|
called sin(). The XSUB will imitate the C function which takes a single
|
|
argument and returns a single value.
|
|
|
|
double
|
|
sin(x)
|
|
double x
|
|
|
|
When using C pointers the indirection operator C<*> should be considered
|
|
part of the type and the address operator C<&> should be considered part of
|
|
the variable, as is demonstrated in the rpcb_gettime() function above. See
|
|
the section on typemaps for more about handling qualifiers and unary
|
|
operators in C types.
|
|
|
|
The function name and the return type must be placed on
|
|
separate lines.
|
|
|
|
INCORRECT CORRECT
|
|
|
|
double sin(x) double
|
|
double x sin(x)
|
|
double x
|
|
|
|
The function body may be indented or left-adjusted. The following example
|
|
shows a function with its body left-adjusted. Most examples in this
|
|
document will indent the body.
|
|
|
|
CORRECT
|
|
|
|
double
|
|
sin(x)
|
|
double x
|
|
|
|
=head2 The Argument Stack
|
|
|
|
The argument stack is used to store the values which are
|
|
sent as parameters to the XSUB and to store the XSUB's
|
|
return value. In reality all Perl functions keep their
|
|
values on this stack at the same time, each limited to its
|
|
own range of positions on the stack. In this document the
|
|
first position on that stack which belongs to the active
|
|
function will be referred to as position 0 for that function.
|
|
|
|
XSUBs refer to their stack arguments with the macro B<ST(x)>, where I<x>
|
|
refers to a position in this XSUB's part of the stack. Position 0 for that
|
|
function would be known to the XSUB as ST(0). The XSUB's incoming
|
|
parameters and outgoing return values always begin at ST(0). For many
|
|
simple cases the B<xsubpp> compiler will generate the code necessary to
|
|
handle the argument stack by embedding code fragments found in the
|
|
typemaps. In more complex cases the programmer must supply the code.
|
|
|
|
=head2 The RETVAL Variable
|
|
|
|
The RETVAL variable is a magic variable which always matches
|
|
the return type of the C library function. The B<xsubpp> compiler will
|
|
supply this variable in each XSUB and by default will use it to hold the
|
|
return value of the C library function being called. In simple cases the
|
|
value of RETVAL will be placed in ST(0) of the argument stack where it can
|
|
be received by Perl as the return value of the XSUB.
|
|
|
|
If the XSUB has a return type of C<void> then the compiler will
|
|
not supply a RETVAL variable for that function. When using
|
|
the PPCODE: directive the RETVAL variable is not needed, unless used
|
|
explicitly.
|
|
|
|
If PPCODE: directive is not used, C<void> return value should be used
|
|
only for subroutines which do not return a value, I<even if> CODE:
|
|
directive is used which sets ST(0) explicitly.
|
|
|
|
Older versions of this document recommended to use C<void> return
|
|
value in such cases. It was discovered that this could lead to
|
|
segfaults in cases when XSUB was I<truly> C<void>. This practice is
|
|
now deprecated, and may be not supported at some future version. Use
|
|
the return value C<SV *> in such cases. (Currently C<xsubpp> contains
|
|
some heuristic code which tries to disambiguate between "truly-void"
|
|
and "old-practice-declared-as-void" functions. Hence your code is at
|
|
mercy of this heuristics unless you use C<SV *> as return value.)
|
|
|
|
=head2 The MODULE Keyword
|
|
|
|
The MODULE keyword is used to start the XS code and to
|
|
specify the package of the functions which are being
|
|
defined. All text preceding the first MODULE keyword is
|
|
considered C code and is passed through to the output
|
|
untouched. Every XS module will have a bootstrap function
|
|
which is used to hook the XSUBs into Perl. The package name
|
|
of this bootstrap function will match the value of the last
|
|
MODULE statement in the XS source files. The value of
|
|
MODULE should always remain constant within the same XS
|
|
file, though this is not required.
|
|
|
|
The following example will start the XS code and will place
|
|
all functions in a package named RPC.
|
|
|
|
MODULE = RPC
|
|
|
|
=head2 The PACKAGE Keyword
|
|
|
|
When functions within an XS source file must be separated into packages
|
|
the PACKAGE keyword should be used. This keyword is used with the MODULE
|
|
keyword and must follow immediately after it when used.
|
|
|
|
MODULE = RPC PACKAGE = RPC
|
|
|
|
[ XS code in package RPC ]
|
|
|
|
MODULE = RPC PACKAGE = RPCB
|
|
|
|
[ XS code in package RPCB ]
|
|
|
|
MODULE = RPC PACKAGE = RPC
|
|
|
|
[ XS code in package RPC ]
|
|
|
|
Although this keyword is optional and in some cases provides redundant
|
|
information it should always be used. This keyword will ensure that the
|
|
XSUBs appear in the desired package.
|
|
|
|
=head2 The PREFIX Keyword
|
|
|
|
The PREFIX keyword designates prefixes which should be
|
|
removed from the Perl function names. If the C function is
|
|
C<rpcb_gettime()> and the PREFIX value is C<rpcb_> then Perl will
|
|
see this function as C<gettime()>.
|
|
|
|
This keyword should follow the PACKAGE keyword when used.
|
|
If PACKAGE is not used then PREFIX should follow the MODULE
|
|
keyword.
|
|
|
|
MODULE = RPC PREFIX = rpc_
|
|
|
|
MODULE = RPC PACKAGE = RPCB PREFIX = rpcb_
|
|
|
|
=head2 The OUTPUT: Keyword
|
|
|
|
The OUTPUT: keyword indicates that certain function parameters should be
|
|
updated (new values made visible to Perl) when the XSUB terminates or that
|
|
certain values should be returned to the calling Perl function. For
|
|
simple functions, such as the sin() function above, the RETVAL variable is
|
|
automatically designated as an output value. In more complex functions
|
|
the B<xsubpp> compiler will need help to determine which variables are output
|
|
variables.
|
|
|
|
This keyword will normally be used to complement the CODE: keyword.
|
|
The RETVAL variable is not recognized as an output variable when the
|
|
CODE: keyword is present. The OUTPUT: keyword is used in this
|
|
situation to tell the compiler that RETVAL really is an output
|
|
variable.
|
|
|
|
The OUTPUT: keyword can also be used to indicate that function parameters
|
|
are output variables. This may be necessary when a parameter has been
|
|
modified within the function and the programmer would like the update to
|
|
be seen by Perl.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep
|
|
OUTPUT:
|
|
timep
|
|
|
|
The OUTPUT: keyword will also allow an output parameter to
|
|
be mapped to a matching piece of code rather than to a
|
|
typemap.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep
|
|
OUTPUT:
|
|
timep sv_setnv(ST(1), (double)timep);
|
|
|
|
B<xsubpp> emits an automatic C<SvSETMAGIC()> for all parameters in the
|
|
OUTPUT section of the XSUB, except RETVAL. This is the usually desired
|
|
behavior, as it takes care of properly invoking 'set' magic on output
|
|
parameters (needed for hash or array element parameters that must be
|
|
created if they didn't exist). If for some reason, this behavior is
|
|
not desired, the OUTPUT section may contain a C<SETMAGIC: DISABLE> line
|
|
to disable it for the remainder of the parameters in the OUTPUT section.
|
|
Likewise, C<SETMAGIC: ENABLE> can be used to reenable it for the
|
|
remainder of the OUTPUT section. See L<perlguts> for more details
|
|
about 'set' magic.
|
|
|
|
=head2 The CODE: Keyword
|
|
|
|
This keyword is used in more complicated XSUBs which require
|
|
special handling for the C function. The RETVAL variable is
|
|
available but will not be returned unless it is specified
|
|
under the OUTPUT: keyword.
|
|
|
|
The following XSUB is for a C function which requires special handling of
|
|
its parameters. The Perl usage is given first.
|
|
|
|
$status = rpcb_gettime( "localhost", $timep );
|
|
|
|
The XSUB follows.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t timep
|
|
CODE:
|
|
RETVAL = rpcb_gettime( host, &timep );
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
=head2 The INIT: Keyword
|
|
|
|
The INIT: keyword allows initialization to be inserted into the XSUB before
|
|
the compiler generates the call to the C function. Unlike the CODE: keyword
|
|
above, this keyword does not affect the way the compiler handles RETVAL.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep
|
|
INIT:
|
|
printf("# Host is %s\n", host );
|
|
OUTPUT:
|
|
timep
|
|
|
|
=head2 The NO_INIT Keyword
|
|
|
|
The NO_INIT keyword is used to indicate that a function
|
|
parameter is being used only as an output value. The B<xsubpp>
|
|
compiler will normally generate code to read the values of
|
|
all function parameters from the argument stack and assign
|
|
them to C variables upon entry to the function. NO_INIT
|
|
will tell the compiler that some parameters will be used for
|
|
output rather than for input and that they will be handled
|
|
before the function terminates.
|
|
|
|
The following example shows a variation of the rpcb_gettime() function.
|
|
This function uses the timep variable only as an output variable and does
|
|
not care about its initial contents.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep = NO_INIT
|
|
OUTPUT:
|
|
timep
|
|
|
|
=head2 Initializing Function Parameters
|
|
|
|
Function parameters are normally initialized with their
|
|
values from the argument stack. The typemaps contain the
|
|
code segments which are used to transfer the Perl values to
|
|
the C parameters. The programmer, however, is allowed to
|
|
override the typemaps and supply alternate (or additional)
|
|
initialization code.
|
|
|
|
The following code demonstrates how to supply initialization code for
|
|
function parameters. The initialization code is eval'd within double
|
|
quotes by the compiler before it is added to the output so anything
|
|
which should be interpreted literally [mainly C<$>, C<@>, or C<\\>]
|
|
must be protected with backslashes. The variables C<$var>, C<$arg>,
|
|
and C<$type> can be used as in typemaps.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host = (char *)SvPV($arg,PL_na);
|
|
time_t &timep = 0;
|
|
OUTPUT:
|
|
timep
|
|
|
|
This should not be used to supply default values for parameters. One
|
|
would normally use this when a function parameter must be processed by
|
|
another library function before it can be used. Default parameters are
|
|
covered in the next section.
|
|
|
|
If the initialization begins with C<=>, then it is output on
|
|
the same line where the input variable is declared. If the
|
|
initialization begins with C<;> or C<+>, then it is output after
|
|
all of the input variables have been declared. The C<=> and C<;>
|
|
cases replace the initialization normally supplied from the typemap.
|
|
For the C<+> case, the initialization from the typemap will precede
|
|
the initialization code included after the C<+>. A global
|
|
variable, C<%v>, is available for the truly rare case where
|
|
information from one initialization is needed in another
|
|
initialization.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
time_t &timep ; /*\$v{time}=@{[$v{time}=$arg]}*/
|
|
char *host + SvOK($v{time}) ? SvPV($arg,PL_na) : NULL;
|
|
OUTPUT:
|
|
timep
|
|
|
|
=head2 Default Parameter Values
|
|
|
|
Default values can be specified for function parameters by
|
|
placing an assignment statement in the parameter list. The
|
|
default value may be a number or a string. Defaults should
|
|
always be used on the right-most parameters only.
|
|
|
|
To allow the XSUB for rpcb_gettime() to have a default host
|
|
value the parameters to the XSUB could be rearranged. The
|
|
XSUB will then call the real rpcb_gettime() function with
|
|
the parameters in the correct order. Perl will call this
|
|
XSUB with either of the following statements.
|
|
|
|
$status = rpcb_gettime( $timep, $host );
|
|
|
|
$status = rpcb_gettime( $timep );
|
|
|
|
The XSUB will look like the code which follows. A CODE:
|
|
block is used to call the real rpcb_gettime() function with
|
|
the parameters in the correct order for that function.
|
|
|
|
bool_t
|
|
rpcb_gettime(timep,host="localhost")
|
|
char *host
|
|
time_t timep = NO_INIT
|
|
CODE:
|
|
RETVAL = rpcb_gettime( host, &timep );
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
=head2 The PREINIT: Keyword
|
|
|
|
The PREINIT: keyword allows extra variables to be declared before the
|
|
typemaps are expanded. If a variable is declared in a CODE: block then that
|
|
variable will follow any typemap code. This may result in a C syntax
|
|
error. To force the variable to be declared before the typemap code, place
|
|
it into a PREINIT: block. The PREINIT: keyword may be used one or more
|
|
times within an XSUB.
|
|
|
|
The following examples are equivalent, but if the code is using complex
|
|
typemaps then the first example is safer.
|
|
|
|
bool_t
|
|
rpcb_gettime(timep)
|
|
time_t timep = NO_INIT
|
|
PREINIT:
|
|
char *host = "localhost";
|
|
CODE:
|
|
RETVAL = rpcb_gettime( host, &timep );
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
A correct, but error-prone example.
|
|
|
|
bool_t
|
|
rpcb_gettime(timep)
|
|
time_t timep = NO_INIT
|
|
CODE:
|
|
char *host = "localhost";
|
|
RETVAL = rpcb_gettime( host, &timep );
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
=head2 The SCOPE: Keyword
|
|
|
|
The SCOPE: keyword allows scoping to be enabled for a particular XSUB. If
|
|
enabled, the XSUB will invoke ENTER and LEAVE automatically.
|
|
|
|
To support potentially complex type mappings, if a typemap entry used
|
|
by this XSUB contains a comment like C</*scope*/> then scoping will
|
|
automatically be enabled for that XSUB.
|
|
|
|
To enable scoping:
|
|
|
|
SCOPE: ENABLE
|
|
|
|
To disable scoping:
|
|
|
|
SCOPE: DISABLE
|
|
|
|
=head2 The INPUT: Keyword
|
|
|
|
The XSUB's parameters are usually evaluated immediately after entering the
|
|
XSUB. The INPUT: keyword can be used to force those parameters to be
|
|
evaluated a little later. The INPUT: keyword can be used multiple times
|
|
within an XSUB and can be used to list one or more input variables. This
|
|
keyword is used with the PREINIT: keyword.
|
|
|
|
The following example shows how the input parameter C<timep> can be
|
|
evaluated late, after a PREINIT.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
PREINIT:
|
|
time_t tt;
|
|
INPUT:
|
|
time_t timep
|
|
CODE:
|
|
RETVAL = rpcb_gettime( host, &tt );
|
|
timep = tt;
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
The next example shows each input parameter evaluated late.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
PREINIT:
|
|
time_t tt;
|
|
INPUT:
|
|
char *host
|
|
PREINIT:
|
|
char *h;
|
|
INPUT:
|
|
time_t timep
|
|
CODE:
|
|
h = host;
|
|
RETVAL = rpcb_gettime( h, &tt );
|
|
timep = tt;
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
=head2 Variable-length Parameter Lists
|
|
|
|
XSUBs can have variable-length parameter lists by specifying an ellipsis
|
|
C<(...)> in the parameter list. This use of the ellipsis is similar to that
|
|
found in ANSI C. The programmer is able to determine the number of
|
|
arguments passed to the XSUB by examining the C<items> variable which the
|
|
B<xsubpp> compiler supplies for all XSUBs. By using this mechanism one can
|
|
create an XSUB which accepts a list of parameters of unknown length.
|
|
|
|
The I<host> parameter for the rpcb_gettime() XSUB can be
|
|
optional so the ellipsis can be used to indicate that the
|
|
XSUB will take a variable number of parameters. Perl should
|
|
be able to call this XSUB with either of the following statements.
|
|
|
|
$status = rpcb_gettime( $timep, $host );
|
|
|
|
$status = rpcb_gettime( $timep );
|
|
|
|
The XS code, with ellipsis, follows.
|
|
|
|
bool_t
|
|
rpcb_gettime(timep, ...)
|
|
time_t timep = NO_INIT
|
|
PREINIT:
|
|
char *host = "localhost";
|
|
STRLEN n_a;
|
|
CODE:
|
|
if( items > 1 )
|
|
host = (char *)SvPV(ST(1), n_a);
|
|
RETVAL = rpcb_gettime( host, &timep );
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
=head2 The C_ARGS: Keyword
|
|
|
|
The C_ARGS: keyword allows creating of XSUBS which have different
|
|
calling sequence from Perl than from C, without a need to write
|
|
CODE: or CPPCODE: section. The contents of the C_ARGS: paragraph is
|
|
put as the argument to the called C function without any change.
|
|
|
|
For example, suppose that C function is declared as
|
|
|
|
symbolic nth_derivative(int n, symbolic function, int flags);
|
|
|
|
and that the default flags are kept in a global C variable
|
|
C<default_flags>. Suppose that you want to create an interface which
|
|
is called as
|
|
|
|
$second_deriv = $function->nth_derivative(2);
|
|
|
|
To do this, declare the XSUB as
|
|
|
|
symbolic
|
|
nth_derivative(function, n)
|
|
symbolic function
|
|
int n
|
|
C_ARGS:
|
|
n, function, default_flags
|
|
|
|
=head2 The PPCODE: Keyword
|
|
|
|
The PPCODE: keyword is an alternate form of the CODE: keyword and is used
|
|
to tell the B<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 are not used
|
|
together within the same XSUB.
|
|
|
|
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 C<void> return type for this function tells the B<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
|
|
B<xsubpp> compiler to create a stack pointer available as C<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 L<perlguts> for details about 'set' magic.
|
|
|
|
=head2 Returning Undef And Empty Lists
|
|
|
|
Occasionally the programmer will want to return simply
|
|
C<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 C<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 C<return> in the above
|
|
XSUB, rather than letting control fall through to the end. In those
|
|
situations C<XSRETURN_EMPTY> should be used, instead. This will ensure that
|
|
the XSUB stack is properly adjusted. Consult L<perlguts/"API LISTING"> for
|
|
other C<XSRETURN> macros.
|
|
|
|
=head2 The REQUIRE: Keyword
|
|
|
|
The REQUIRE: keyword is used to indicate the minimum version of the
|
|
B<xsubpp> compiler needed to compile the XS module. An XS module which
|
|
contains the following statement will compile with only B<xsubpp> version
|
|
1.922 or greater:
|
|
|
|
REQUIRE: 1.922
|
|
|
|
=head2 The CLEANUP: Keyword
|
|
|
|
This keyword can be used when an XSUB requires special cleanup procedures
|
|
before it terminates. When the CLEANUP: keyword is used it must follow
|
|
any CODE:, PPCODE:, or OUTPUT: blocks which are present in the XSUB. The
|
|
code specified for the cleanup block will be added as the last statements
|
|
in the XSUB.
|
|
|
|
=head2 The BOOT: Keyword
|
|
|
|
The BOOT: keyword is used to add code to the extension's bootstrap
|
|
function. The bootstrap function is generated by the B<xsubpp> compiler and
|
|
normally holds the statements necessary to register any XSUBs with Perl.
|
|
With the BOOT: keyword the programmer can tell the compiler to add extra
|
|
statements to the bootstrap function.
|
|
|
|
This keyword may be used any time after the first MODULE keyword and should
|
|
appear on a line by itself. The first blank line after the keyword will
|
|
terminate the code block.
|
|
|
|
BOOT:
|
|
# The following message will be printed when the
|
|
# bootstrap function executes.
|
|
printf("Hello from the bootstrap!\n");
|
|
|
|
=head2 The VERSIONCHECK: Keyword
|
|
|
|
The VERSIONCHECK: keyword corresponds to B<xsubpp>'s C<-versioncheck> and
|
|
C<-noversioncheck> options. This keyword overrides the command line
|
|
options. Version checking is enabled by default. When version checking is
|
|
enabled the XS module will attempt to verify that its version matches the
|
|
version of the PM module.
|
|
|
|
To enable version checking:
|
|
|
|
VERSIONCHECK: ENABLE
|
|
|
|
To disable version checking:
|
|
|
|
VERSIONCHECK: DISABLE
|
|
|
|
=head2 The PROTOTYPES: Keyword
|
|
|
|
The PROTOTYPES: keyword corresponds to B<xsubpp>'s C<-prototypes> and
|
|
C<-noprototypes> options. This keyword overrides the command line options.
|
|
Prototypes are enabled by default. When prototypes are enabled XSUBs will
|
|
be given Perl prototypes. This keyword may be used multiple times in an XS
|
|
module to enable and disable prototypes for different parts of the module.
|
|
|
|
To enable prototypes:
|
|
|
|
PROTOTYPES: ENABLE
|
|
|
|
To disable prototypes:
|
|
|
|
PROTOTYPES: DISABLE
|
|
|
|
=head2 The PROTOTYPE: Keyword
|
|
|
|
This keyword is similar to the PROTOTYPES: keyword above but can be used to
|
|
force B<xsubpp> to use a specific prototype for the XSUB. This keyword
|
|
overrides all other prototype options and keywords but affects only the
|
|
current XSUB. Consult L<perlsub/Prototypes> for information about Perl
|
|
prototypes.
|
|
|
|
bool_t
|
|
rpcb_gettime(timep, ...)
|
|
time_t timep = NO_INIT
|
|
PROTOTYPE: $;$
|
|
PREINIT:
|
|
char *host = "localhost";
|
|
STRLEN n_a;
|
|
CODE:
|
|
if( items > 1 )
|
|
host = (char *)SvPV(ST(1), n_a);
|
|
RETVAL = rpcb_gettime( host, &timep );
|
|
OUTPUT:
|
|
timep
|
|
RETVAL
|
|
|
|
=head2 The ALIAS: Keyword
|
|
|
|
The ALIAS: keyword allows an XSUB to have two or more unique Perl names
|
|
and to know which of those names was used when it was invoked. The Perl
|
|
names may be fully-qualified with package names. Each alias is given an
|
|
index. The compiler will setup a variable called C<ix> which contain the
|
|
index of the alias which was used. When the XSUB is called with its
|
|
declared name C<ix> will be 0.
|
|
|
|
The following example will create aliases C<FOO::gettime()> and
|
|
C<BAR::getit()> for this function.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep
|
|
ALIAS:
|
|
FOO::gettime = 1
|
|
BAR::getit = 2
|
|
INIT:
|
|
printf("# ix = %d\n", ix );
|
|
OUTPUT:
|
|
timep
|
|
|
|
=head2 The INTERFACE: Keyword
|
|
|
|
This keyword declares the current XSUB as a keeper of the given
|
|
calling signature. If some text follows this keyword, it is
|
|
considered as a list of functions which have this signature, and
|
|
should be attached to XSUBs.
|
|
|
|
Say, if you have 4 functions multiply(), divide(), add(), subtract() all
|
|
having the signature
|
|
|
|
symbolic f(symbolic, symbolic);
|
|
|
|
you code them all by using XSUB
|
|
|
|
symbolic
|
|
interface_s_ss(arg1, arg2)
|
|
symbolic arg1
|
|
symbolic arg2
|
|
INTERFACE:
|
|
multiply divide
|
|
add subtract
|
|
|
|
The advantage of this approach comparing to ALIAS: keyword is that one
|
|
can attach an extra function remainder() at runtime by using
|
|
|
|
CV *mycv = newXSproto("Symbolic::remainder",
|
|
XS_Symbolic_interface_s_ss, __FILE__, "$$");
|
|
XSINTERFACE_FUNC_SET(mycv, remainder);
|
|
|
|
(This example supposes that there was no INTERFACE_MACRO: section,
|
|
otherwise one needs to use something else instead of
|
|
C<XSINTERFACE_FUNC_SET>.)
|
|
|
|
=head2 The INTERFACE_MACRO: Keyword
|
|
|
|
This keyword allows one to define an INTERFACE using a different way
|
|
to extract a function pointer from an XSUB. The text which follows
|
|
this keyword should give the name of macros which would extract/set a
|
|
function pointer. The extractor macro is given return type, C<CV*>,
|
|
and C<XSANY.any_dptr> for this C<CV*>. The setter macro is given cv,
|
|
and the function pointer.
|
|
|
|
The default value is C<XSINTERFACE_FUNC> and C<XSINTERFACE_FUNC_SET>.
|
|
An INTERFACE keyword with an empty list of functions can be omitted if
|
|
INTERFACE_MACRO keyword is used.
|
|
|
|
Suppose that in the previous example functions pointers for
|
|
multiply(), divide(), add(), subtract() are kept in a global C array
|
|
C<fp[]> with offsets being C<multiply_off>, C<divide_off>, C<add_off>,
|
|
C<subtract_off>. Then one can use
|
|
|
|
#define XSINTERFACE_FUNC_BYOFFSET(ret,cv,f) \
|
|
((XSINTERFACE_CVT(ret,))fp[CvXSUBANY(cv).any_i32])
|
|
#define XSINTERFACE_FUNC_BYOFFSET_set(cv,f) \
|
|
CvXSUBANY(cv).any_i32 = CAT2( f, _off )
|
|
|
|
in C section,
|
|
|
|
symbolic
|
|
interface_s_ss(arg1, arg2)
|
|
symbolic arg1
|
|
symbolic arg2
|
|
INTERFACE_MACRO:
|
|
XSINTERFACE_FUNC_BYOFFSET
|
|
XSINTERFACE_FUNC_BYOFFSET_set
|
|
INTERFACE:
|
|
multiply divide
|
|
add subtract
|
|
|
|
in XSUB section.
|
|
|
|
=head2 The INCLUDE: Keyword
|
|
|
|
This keyword can be used to pull other files into the XS module. The other
|
|
files may have XS code. INCLUDE: can also be used to run a command to
|
|
generate the XS code to be pulled into the module.
|
|
|
|
The file F<Rpcb1.xsh> contains our C<rpcb_gettime()> function:
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep
|
|
OUTPUT:
|
|
timep
|
|
|
|
The XS module can use INCLUDE: to pull that file into it.
|
|
|
|
INCLUDE: Rpcb1.xsh
|
|
|
|
If the parameters to the INCLUDE: keyword are followed by a pipe (C<|>) then
|
|
the compiler will interpret the parameters as a command.
|
|
|
|
INCLUDE: cat Rpcb1.xsh |
|
|
|
|
=head2 The CASE: Keyword
|
|
|
|
The CASE: keyword allows an XSUB to have multiple distinct parts with each
|
|
part acting as a virtual XSUB. CASE: is greedy and if it is used then all
|
|
other XS keywords must be contained within a CASE:. This means nothing may
|
|
precede the first CASE: in the XSUB and anything following the last CASE: is
|
|
included in that case.
|
|
|
|
A CASE: might switch via a parameter of the XSUB, via the C<ix> ALIAS:
|
|
variable (see L<"The ALIAS: Keyword">), or maybe via the C<items> variable
|
|
(see L<"Variable-length Parameter Lists">). The last CASE: becomes the
|
|
B<default> case if it is not associated with a conditional. The following
|
|
example shows CASE switched via C<ix> with a function C<rpcb_gettime()>
|
|
having an alias C<x_gettime()>. When the function is called as
|
|
C<rpcb_gettime()> its parameters are the usual C<(char *host, time_t *timep)>,
|
|
but when the function is called as C<x_gettime()> its parameters are
|
|
reversed, C<(time_t *timep, char *host)>.
|
|
|
|
long
|
|
rpcb_gettime(a,b)
|
|
CASE: ix == 1
|
|
ALIAS:
|
|
x_gettime = 1
|
|
INPUT:
|
|
# 'a' is timep, 'b' is host
|
|
char *b
|
|
time_t a = NO_INIT
|
|
CODE:
|
|
RETVAL = rpcb_gettime( b, &a );
|
|
OUTPUT:
|
|
a
|
|
RETVAL
|
|
CASE:
|
|
# 'a' is host, 'b' is timep
|
|
char *a
|
|
time_t &b = NO_INIT
|
|
OUTPUT:
|
|
b
|
|
RETVAL
|
|
|
|
That function can be called with either of the following statements. Note
|
|
the different argument lists.
|
|
|
|
$status = rpcb_gettime( $host, $timep );
|
|
|
|
$status = x_gettime( $timep, $host );
|
|
|
|
=head2 The & Unary Operator
|
|
|
|
The & unary operator is used to tell the compiler that it should dereference
|
|
the object when it calls the C function. This is used when a CODE: block is
|
|
not used and the object is a not a pointer type (the object is an C<int> or
|
|
C<long> but not a C<int*> or C<long*>).
|
|
|
|
The following XSUB will generate incorrect C code. The xsubpp compiler will
|
|
turn this into code which calls C<rpcb_gettime()> with parameters C<(char
|
|
*host, time_t timep)>, but the real C<rpcb_gettime()> wants the C<timep>
|
|
parameter to be of type C<time_t*> rather than C<time_t>.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t timep
|
|
OUTPUT:
|
|
timep
|
|
|
|
That problem is corrected by using the C<&> operator. The xsubpp compiler
|
|
will now turn this into code which calls C<rpcb_gettime()> correctly with
|
|
parameters C<(char *host, time_t *timep)>. It does this by carrying the
|
|
C<&> through, so the function call looks like C<rpcb_gettime(host, &timep)>.
|
|
|
|
bool_t
|
|
rpcb_gettime(host,timep)
|
|
char *host
|
|
time_t &timep
|
|
OUTPUT:
|
|
timep
|
|
|
|
=head2 Inserting Comments and C Preprocessor Directives
|
|
|
|
C preprocessor directives are allowed within BOOT:, PREINIT: INIT:,
|
|
CODE:, PPCODE:, and CLEANUP: blocks, as well as outside the functions.
|
|
Comments are allowed anywhere after the MODULE keyword. The compiler
|
|
will pass the preprocessor directives through untouched and will remove
|
|
the commented lines.
|
|
|
|
Comments can be added to XSUBs by placing a C<#> as the first
|
|
non-whitespace of a line. Care should be taken to avoid making the
|
|
comment look like a C preprocessor directive, lest it be interpreted as
|
|
such. The simplest way to prevent this is to put whitespace in front of
|
|
the C<#>.
|
|
|
|
If you use preprocessor directives to choose one of two
|
|
versions of a function, use
|
|
|
|
#if ... version1
|
|
#else /* ... version2 */
|
|
#endif
|
|
|
|
and not
|
|
|
|
#if ... version1
|
|
#endif
|
|
#if ... version2
|
|
#endif
|
|
|
|
because otherwise xsubpp will believe that you made a duplicate
|
|
definition of the function. Also, put a blank line before the
|
|
#else/#endif so it will not be seen as part of the function body.
|
|
|
|
=head2 Using XS With C++
|
|
|
|
If a function is defined as a C++ method then it will assume
|
|
its first argument is an object pointer. The object pointer
|
|
will be stored in a variable called THIS. The object should
|
|
have been created by C++ with the new() function and should
|
|
be blessed by Perl with the sv_setref_pv() macro. The
|
|
blessing of the object by Perl can be handled by a typemap. An example
|
|
typemap is shown at the end of this section.
|
|
|
|
If the method is defined as static it will call the C++
|
|
function using the class::method() syntax. If the method is not static
|
|
the function will be called using the THIS-E<gt>method() syntax.
|
|
|
|
The next examples will use the following C++ class.
|
|
|
|
class color {
|
|
public:
|
|
color();
|
|
~color();
|
|
int blue();
|
|
void set_blue( int );
|
|
|
|
private:
|
|
int c_blue;
|
|
};
|
|
|
|
The XSUBs for the blue() and set_blue() methods are defined with the class
|
|
name but the parameter for the object (THIS, or "self") is implicit and is
|
|
not listed.
|
|
|
|
int
|
|
color::blue()
|
|
|
|
void
|
|
color::set_blue( val )
|
|
int val
|
|
|
|
Both functions will expect an object as the first parameter. The xsubpp
|
|
compiler will call that object C<THIS> and will use it to call the specified
|
|
method. So in the C++ code the blue() and set_blue() methods will be called
|
|
in the following manner.
|
|
|
|
RETVAL = THIS->blue();
|
|
|
|
THIS->set_blue( val );
|
|
|
|
If the function's name is B<DESTROY> then the C++ C<delete> function will be
|
|
called and C<THIS> will be given as its parameter.
|
|
|
|
void
|
|
color::DESTROY()
|
|
|
|
The C++ code will call C<delete>.
|
|
|
|
delete THIS;
|
|
|
|
If the function's name is B<new> then the C++ C<new> function will be called
|
|
to create a dynamic C++ object. The XSUB will expect the class name, which
|
|
will be kept in a variable called C<CLASS>, to be given as the first
|
|
argument.
|
|
|
|
color *
|
|
color::new()
|
|
|
|
The C++ code will call C<new>.
|
|
|
|
RETVAL = new color();
|
|
|
|
The following is an example of a typemap that could be used for this C++
|
|
example.
|
|
|
|
TYPEMAP
|
|
color * O_OBJECT
|
|
|
|
OUTPUT
|
|
# The Perl object is blessed into 'CLASS', which should be a
|
|
# char* having the name of the package for the blessing.
|
|
O_OBJECT
|
|
sv_setref_pv( $arg, CLASS, (void*)$var );
|
|
|
|
INPUT
|
|
O_OBJECT
|
|
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
|
|
$var = ($type)SvIV((SV*)SvRV( $arg ));
|
|
else{
|
|
warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
|
|
XSRETURN_UNDEF;
|
|
}
|
|
|
|
=head2 Interface Strategy
|
|
|
|
When designing an interface between Perl and a C library a straight
|
|
translation from C to XS is often sufficient. The interface will often be
|
|
very C-like and occasionally nonintuitive, especially when the C function
|
|
modifies one of its parameters. In cases where the programmer wishes to
|
|
create a more Perl-like interface the following strategy may help to
|
|
identify the more critical parts of the interface.
|
|
|
|
Identify the C functions which modify their parameters. The XSUBs for
|
|
these functions may be able to return lists to Perl, or may be
|
|
candidates to return undef or an empty list in case of failure.
|
|
|
|
Identify which values are used by only the C and XSUB functions
|
|
themselves. If Perl does not need to access the contents of the value
|
|
then it may not be necessary to provide a translation for that value
|
|
from C to Perl.
|
|
|
|
Identify the pointers in the C function parameter lists and return
|
|
values. Some pointers can be handled in XS with the & unary operator on
|
|
the variable name while others will require the use of the * operator on
|
|
the type name. In general it is easier to work with the & operator.
|
|
|
|
Identify the structures used by the C functions. In many
|
|
cases it may be helpful to use the T_PTROBJ typemap for
|
|
these structures so they can be manipulated by Perl as
|
|
blessed objects.
|
|
|
|
=head2 Perl Objects And C Structures
|
|
|
|
When dealing with C structures one should select either
|
|
B<T_PTROBJ> or B<T_PTRREF> for the XS type. Both types are
|
|
designed to handle pointers to complex objects. The
|
|
T_PTRREF type will allow the Perl object to be unblessed
|
|
while the T_PTROBJ type requires that the object be blessed.
|
|
By using T_PTROBJ one can achieve a form of type-checking
|
|
because the XSUB will attempt to verify that the Perl object
|
|
is of the expected type.
|
|
|
|
The following XS code shows the getnetconfigent() function which is used
|
|
with ONC+ TIRPC. The getnetconfigent() function will return a pointer to a
|
|
C structure and has the C prototype shown below. The example will
|
|
demonstrate how the C pointer will become a Perl reference. Perl will
|
|
consider this reference to be a pointer to a blessed object and will
|
|
attempt to call a destructor for the object. A destructor will be
|
|
provided in the XS source to free the memory used by getnetconfigent().
|
|
Destructors in XS can be created by specifying an XSUB function whose name
|
|
ends with the word B<DESTROY>. XS destructors can be used to free memory
|
|
which may have been malloc'd by another XSUB.
|
|
|
|
struct netconfig *getnetconfigent(const char *netid);
|
|
|
|
A C<typedef> will be created for C<struct netconfig>. The Perl
|
|
object will be blessed in a class matching the name of the C
|
|
type, with the tag C<Ptr> appended, and the name should not
|
|
have embedded spaces if it will be a Perl package name. The
|
|
destructor will be placed in a class corresponding to the
|
|
class of the object and the PREFIX keyword will be used to
|
|
trim the name to the word DESTROY as Perl will expect.
|
|
|
|
typedef struct netconfig Netconfig;
|
|
|
|
MODULE = RPC PACKAGE = RPC
|
|
|
|
Netconfig *
|
|
getnetconfigent(netid)
|
|
char *netid
|
|
|
|
MODULE = RPC PACKAGE = NetconfigPtr PREFIX = rpcb_
|
|
|
|
void
|
|
rpcb_DESTROY(netconf)
|
|
Netconfig *netconf
|
|
CODE:
|
|
printf("Now in NetconfigPtr::DESTROY\n");
|
|
free( netconf );
|
|
|
|
This example requires the following typemap entry. Consult the typemap
|
|
section for more information about adding new typemaps for an extension.
|
|
|
|
TYPEMAP
|
|
Netconfig * T_PTROBJ
|
|
|
|
This example will be used with the following Perl statements.
|
|
|
|
use RPC;
|
|
$netconf = getnetconfigent("udp");
|
|
|
|
When Perl destroys the object referenced by $netconf it will send the
|
|
object to the supplied XSUB DESTROY function. Perl cannot determine, and
|
|
does not care, that this object is a C struct and not a Perl object. In
|
|
this sense, there is no difference between the object created by the
|
|
getnetconfigent() XSUB and an object created by a normal Perl subroutine.
|
|
|
|
=head2 The Typemap
|
|
|
|
The typemap is a collection of code fragments which are used by the B<xsubpp>
|
|
compiler to map C function parameters and values to Perl values. The
|
|
typemap file may consist of three sections labeled C<TYPEMAP>, C<INPUT>, and
|
|
C<OUTPUT>. Any unlabelled initial section is assumed to be a C<TYPEMAP>
|
|
section if a name is not explicitly specified. The INPUT section tells
|
|
the compiler how to translate Perl values
|
|
into variables of certain C types. The OUTPUT section tells the compiler
|
|
how to translate the values from certain C types into values Perl can
|
|
understand. The TYPEMAP section tells the compiler which of the INPUT and
|
|
OUTPUT code fragments should be used to map a given C type to a Perl value.
|
|
The section labels C<TYPEMAP>, C<INPUT>, or C<OUTPUT> must begin
|
|
in the first column on a line by themselves, and must be in uppercase.
|
|
|
|
The default typemap in the C<ext> directory of the Perl source contains many
|
|
useful types which can be used by Perl extensions. Some extensions define
|
|
additional typemaps which they keep in their own directory. These
|
|
additional typemaps may reference INPUT and OUTPUT maps in the main
|
|
typemap. The B<xsubpp> compiler will allow the extension's own typemap to
|
|
override any mappings which are in the default typemap.
|
|
|
|
Most extensions which require a custom typemap will need only the TYPEMAP
|
|
section of the typemap file. The custom typemap used in the
|
|
getnetconfigent() example shown earlier demonstrates what may be the typical
|
|
use of extension typemaps. That typemap is used to equate a C structure
|
|
with the T_PTROBJ typemap. The typemap used by getnetconfigent() is shown
|
|
here. Note that the C type is separated from the XS type with a tab and
|
|
that the C unary operator C<*> is considered to be a part of the C type name.
|
|
|
|
TYPEMAP
|
|
Netconfig *<tab>T_PTROBJ
|
|
|
|
Here's a more complicated example: suppose that you wanted C<struct
|
|
netconfig> to be blessed into the class C<Net::Config>. One way to do
|
|
this is to use underscores (_) to separate package names, as follows:
|
|
|
|
typedef struct netconfig * Net_Config;
|
|
|
|
And then provide a typemap entry C<T_PTROBJ_SPECIAL> that maps underscores to
|
|
double-colons (::), and declare C<Net_Config> to be of that type:
|
|
|
|
|
|
TYPEMAP
|
|
Net_Config T_PTROBJ_SPECIAL
|
|
|
|
INPUT
|
|
T_PTROBJ_SPECIAL
|
|
if (sv_derived_from($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")) {
|
|
IV tmp = SvIV((SV*)SvRV($arg));
|
|
$var = ($type) tmp;
|
|
}
|
|
else
|
|
croak(\"$var is not of type ${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")
|
|
|
|
OUTPUT
|
|
T_PTROBJ_SPECIAL
|
|
sv_setref_pv($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\",
|
|
(void*)$var);
|
|
|
|
The INPUT and OUTPUT sections substitute underscores for double-colons
|
|
on the fly, giving the desired effect. This example demonstrates some
|
|
of the power and versatility of the typemap facility.
|
|
|
|
=head1 EXAMPLES
|
|
|
|
File C<RPC.xs>: Interface to some ONC+ RPC bind library functions.
|
|
|
|
#include "EXTERN.h"
|
|
#include "perl.h"
|
|
#include "XSUB.h"
|
|
|
|
#include <rpc/rpc.h>
|
|
|
|
typedef struct netconfig Netconfig;
|
|
|
|
MODULE = RPC PACKAGE = RPC
|
|
|
|
SV *
|
|
rpcb_gettime(host="localhost")
|
|
char *host
|
|
PREINIT:
|
|
time_t timep;
|
|
CODE:
|
|
ST(0) = sv_newmortal();
|
|
if( rpcb_gettime( host, &timep ) )
|
|
sv_setnv( ST(0), (double)timep );
|
|
|
|
Netconfig *
|
|
getnetconfigent(netid="udp")
|
|
char *netid
|
|
|
|
MODULE = RPC PACKAGE = NetconfigPtr PREFIX = rpcb_
|
|
|
|
void
|
|
rpcb_DESTROY(netconf)
|
|
Netconfig *netconf
|
|
CODE:
|
|
printf("NetconfigPtr::DESTROY\n");
|
|
free( netconf );
|
|
|
|
File C<typemap>: Custom typemap for RPC.xs.
|
|
|
|
TYPEMAP
|
|
Netconfig * T_PTROBJ
|
|
|
|
File C<RPC.pm>: Perl module for the RPC extension.
|
|
|
|
package RPC;
|
|
|
|
require Exporter;
|
|
require DynaLoader;
|
|
@ISA = qw(Exporter DynaLoader);
|
|
@EXPORT = qw(rpcb_gettime getnetconfigent);
|
|
|
|
bootstrap RPC;
|
|
1;
|
|
|
|
File C<rpctest.pl>: Perl test program for the RPC extension.
|
|
|
|
use RPC;
|
|
|
|
$netconf = getnetconfigent();
|
|
$a = rpcb_gettime();
|
|
print "time = $a\n";
|
|
print "netconf = $netconf\n";
|
|
|
|
$netconf = getnetconfigent("tcp");
|
|
$a = rpcb_gettime("poplar");
|
|
print "time = $a\n";
|
|
print "netconf = $netconf\n";
|
|
|
|
|
|
=head1 XS VERSION
|
|
|
|
This document covers features supported by C<xsubpp> 1.935.
|
|
|
|
=head1 AUTHOR
|
|
|
|
Dean Roehrich <F<[email protected]>>
|
|
Jul 8, 1996
|