This keyword is similar to the PROTOTYPES: keyword above but can be used to
force 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 perlsub/Prototypes for information about Perl
prototypes.
If the prototypes are enabled, you can disable it locally for a given
XSUB as in the following example:
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 ix which contain the
index of the alias which was used. When the XSUB is called with its
declared name ix will be 0.
Instead of writing an overloaded interface using pure Perl, you
can also use the OVERLOAD keyword to define additional Perl names
for your functions (like the ALIAS: keyword above). However, the
overloaded functions must be defined with three parameters (except
for the nomethod() function which needs four parameters). If any
function has the OVERLOAD: keyword, several additional lines
will be defined in the c file generated by xsubpp in order to
register with the overload magic.
Since blessed objects are actually stored as RV's, it is useful
to use the typemap features to preprocess parameters and extract
the actual SV stored within the blessed RV. See the sample for
T_PTROBJ_SPECIAL below.
To use the OVERLOAD: keyword, create an XS function which takes
three input parameters ( or use the c style '...' definition) like
this:
in paragraph 282.where FALLBACK can take any of the three values TRUE, FALSE, or
UNDEF. If you do not set any FALLBACK value when using OVERLOAD,
it defaults to UNDEF. FALLBACK is not used except when one or
more functions using OVERLOAD have been defined. Please see
overload/Fallback for more details.
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 the current XSUB.
For example, if you have 4 C functions multiply(), divide(), add(),
subtract() all having the signature:
symbolic f(symbolic, symbolic);
you can make them all to use the same XSUB using this:
symbolic
interface_s_ss(arg1, arg2)
symbolic arg1
symbolic arg2
INTERFACE:
multiply divide
add subtract
(This is the complete XSUB code for 4 Perl functions!) Four generated
Perl function share names with corresponding C functions.
The advantage of this approach comparing to ALIAS: keyword is that there
is no need to code a switch statement, each Perl function (which shares
the same XSUB) knows which C function it should call. Additionally, 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);
say, from another XSUB. (This example supposes that there was no
INTERFACE_MACRO: section, otherwise one needs to use something else instead of
XSINTERFACE_FUNC_SET, see the next section.)
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, CV*,
and XSANY.any_dptr for this CV*. The setter macro is given cv,
and the function pointer.
The default value is XSINTERFACE_FUNC and 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
fp[] with offsets being multiply_off, divide_off, add_off,
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.
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 Rpcb1.xsh contains our 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 (|) then
the compiler will interpret the parameters as a command.
INCLUDE: cat Rpcb1.xsh |
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 ix ALIAS:
variable (see The ALIAS: Keyword), or maybe via the items variable
(see Variable-length Parameter Lists). The last CASE: becomes the
default case if it is not associated with a conditional. The following
example shows CASE switched via ix with a function rpcb_gettime()
having an alias x_gettime(). When the function is called as
rpcb_gettime() its parameters are the usual (char *host, time_t *timep),
but when the function is called as x_gettime() its parameters are
reversed, (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 );
The & unary operator in the INPUT: section is used to tell xsubpp
that it should convert a Perl value to/from C using the C type to the left
of &, but provide a pointer to this value when the C function is called.
This is useful to avoid a CODE: block for a C function which takes a parameter
by reference. Typically, the parameter should be not a pointer type (an
int or long but not an int* or long*).
The following XSUB will generate incorrect C code. The xsubpp compiler will
turn this into code which calls rpcb_gettime() with parameters (char
*host, time_t timep), but the real rpcb_gettime() wants the timep
parameter to be of type time_t* rather than time_t.
bool_t
rpcb_gettime(host,timep)
char *host
time_t timep
OUTPUT:
timep
That problem is corrected by using the & operator. The xsubpp compiler
will now turn this into code which calls rpcb_gettime() correctly with
parameters (char *host, time_t *timep). It does this by carrying the
& through, so the function call looks like rpcb_gettime(host, &timep).
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
OUTPUT:
timep
C preprocessor directives are allowed within BOOT:, PREINIT: INIT:, CODE:,
PPCODE:, POSTCALL:, 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. POD documentation is allowed at any point, both in the
C and XS language sections. POD must be terminated with a =cut command;
xsubpp will exit with an error if it does not. It is very unlikely that
human generated C code will be mistaken for POD, as most indenting styles
result in whitespace in front of any line starting with =. Machine
generated XS files may fall into this trap unless care is taken to
ensure that a space breaks the sequence ``\n=''.
Comments can be added to XSUBs by placing a # 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 #.
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.
If an XSUB name contains ::, it is considered to be a C++ method.
The generated Perl function will assume that
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 return type of the XSUB includes static, the method is considered
to be a static method. 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->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 Perl functions will expect an object as the first parameter. In the
generated C++ code the object is called THIS, and the method call will
be performed on this object. So in the C++ code the blue() and set_blue()
methods will be called as this:
RETVAL = THIS->blue();
THIS->set_blue( val );
You could also write a single get/set method using an optional argument:
int
color::blue( val = NO_INIT )
int val
PROTOTYPE $;$
CODE:
if (items > 1)
THIS->set_blue( val );
RETVAL = THIS->blue();
OUTPUT:
RETVAL
If the function's name is DESTROY then the C++ delete function will be
called and THIS will be given as its parameter. The generated C++ code for
void
color::DESTROY()
will look like this:
color *THIS = ...; // Initialized as in typemap
delete THIS;
If the function's name is new then the 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 CLASS, to be given as the first
argument.
color *
color::new()
The generated C++ code will call 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;
}
When designing an interface between Perl and a C library a straight
translation from C to XS (such as created by h2xs -x) is often sufficient.
However, sometimes the interface will look
very C-like and occasionally nonintuitive, especially when the C function
modifies one of its parameters, or returns failure inband (as in ``negative
return values mean failure''). 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 with input/output or output parameters. The XSUBs for
these functions may be able to return lists to Perl.
Identify the C functions which use some inband info as an indication
of failure. They may be
candidates to return undef or an empty list in case of failure. If the
failure may be detected without a call to the C function, you may want to use
an INIT: section to report the failure. For failures detectable after the C
function returns one may want to use a POSTCALL: section to process the
failure. In more complicated cases use CODE: or PPCODE: sections.
If many functions use the same failure indication based on the return value,
you may want to create a special typedef to handle this situation. Put
typedef int negative_is_failure;
near the beginning of XS file, and create an OUTPUT typemap entry
for negative_is_failure which converts negative values to undef, or
maybe croak()s. After this the return value of type negative_is_failure
will create more Perl-like interface.
Identify which values are used by only the C and XSUB functions
themselves, say, when a parameter to a function should be a contents of a
global variable. 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 may be used to implement input/output or
output parameters, they can be handled in XS with the & unary operator,
and, possibly, using the NO_INIT keyword.
Some others will require handling of types like int *, and one needs
to decide what a useful Perl translation will do in such a case. When
the semantic is clear, it is advisable to put the translation into a typemap
file.
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. (This is handled automatically by h2xs -x.)
If the same C type is used in several different contexts which require
different translations, typedef several new types mapped to this C type,
and create separate typemap entries for these new types. Use these
types in declarations of return type and parameters to XSUBs.
When dealing with C structures one should select either
T_PTROBJ or 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 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 typedef will be created for struct netconfig. The Perl
object will be blessed in a class matching the name of the C
type, with the tag 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.
The typemap is a collection of code fragments which are used by the xsubpp
compiler to map C function parameters and values to Perl values. The
typemap file may consist of three sections labelled TYPEMAP, INPUT, and
OUTPUT. An unlabelled initial section is assumed to be a TYPEMAP
section. 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 TYPEMAP, INPUT, or OUTPUT must begin
in the first column on a line by themselves, and must be in uppercase.
The default typemap in the lib/ExtUtils 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 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 * 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 struct
netconfig to be blessed into the class 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 T_PTROBJ_SPECIAL that maps underscores to
double-colons (::), and declare 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 = INT2PTR($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.
The INT2PTR macro (defined in perl.h) casts an integer to a pointer,
of a given type, taking care of the possible different size of integers
and pointers. There are also PTR2IV, PTR2UV, PTR2NV macros,
to map the other way, which may be useful in OUTPUT sections.
Starting with Perl 5.8, a macro framework has been defined to allow
static data to be safely stored in XS modules that will be accessed from
a multi-threaded Perl.
Although primarily designed for use with multi-threaded Perl, the macros
have been designed so that they will work with non-threaded Perl as well.
It is therefore strongly recommended that these macros be used by all
XS modules that make use of static data.
perldoc2tree.cgi: /usr/lib/perl5/5.8.8/pod/perlxs.pod: cannot resolve L in paragraph 401.
The easiest way to get a template set of macros to use is by specifying
the -g (--global) option with h2xs (see h2xs).
Below is an example module that makes use of the macros.
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
/* Global Data */
#define MY_CXT_KEY "BlindMice::_guts" XS_VERSION
typedef struct {
int count;
char name[3][100];
} my_cxt_t;
START_MY_CXT
MODULE = BlindMice PACKAGE = BlindMice
BOOT:
{
MY_CXT_INIT;
MY_CXT.count = 0;
strcpy(MY_CXT.name[0], "None");
strcpy(MY_CXT.name[1], "None");
strcpy(MY_CXT.name[2], "None");
}
int
newMouse(char * name)
char * name;
PREINIT:
dMY_CXT;
CODE:
if (MY_CXT.count >= 3) {
warn("Already have 3 blind mice");
RETVAL = 0;
}
else {
RETVAL = ++ MY_CXT.count;
strcpy(MY_CXT.name[MY_CXT.count - 1], name);
}
char *
get_mouse_name(index)
int index
CODE:
dMY_CXT;
RETVAL = MY_CXT.lives ++;
if (index > MY_CXT.count)
croak("There are only 3 blind mice.");
else
RETVAL = newSVpv(MY_CXT.name[index - 1]);
REFERENCE
- MY_CXT_KEY
-
This macro is used to define a unique key to refer to the static data
for an XS module. The suggested naming scheme, as used by h2xs, is to
use a string that consists of the module name, the string ``::_guts''
and the module version number.
-
#define MY_CXT_KEY "MyModule::_guts" XS_VERSION
- typedef my_cxt_t
-
This struct typedef must always be called my_cxt_t -- the other
CXT* macros assume the existence of the my_cxt_t typedef name.
-
Declare a typedef named my_cxt_t that is a structure that contains
all the data that needs to be interpreter-local.
-
typedef struct {
int some_value;
} my_cxt_t;
- START_MY_CXT
-
Always place the START_MY_CXT macro directly after the declaration
of my_cxt_t.
- MY_CXT_INIT
-
The MY_CXT_INIT macro initialises storage for the my_cxt_t struct.
-
It must be called exactly once -- typically in a BOOT: section.
- dMY_CXT
-
Use the dMY_CXT macro (a declaration) in all the functions that access
MY_CXT.
- MY_CXT
-
Use the MY_CXT macro to access members of the my_cxt_t struct. For
example, if my_cxt_t is
-
typedef struct {
int index;
} my_cxt_t;
-
then use this to access the index member
-
dMY_CXT;
MY_CXT.index = 2;
File 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 typemap: Custom typemap for RPC.xs.
TYPEMAP
Netconfig * T_PTROBJ
File 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 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";
This document covers features supported by xsubpp 1.935.
Originally written by Dean Roehrich <roehrich@cray.com>.
Maintained since 1996 by The Perl Porters <perlbug@perl.org>.
© Copyright 1997 - 2011 Virtual Solutions. All Rights Reserved.