perlxs (1)
Leading comments
Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) Standard preamble: ========================================================================
NAME
perlxs - XS language reference manualDESCRIPTION
Introduction
Before writing
An
The glue code pulls the arguments from the Perl stack, converts these Perl values to the formats expected by a C function, call this C function, transfers the return values of the C function back to Perl. Return values here may be a conventional C return value or any C function arguments that may serve as output parameters. These return values may be passed back to Perl either by putting them on the Perl stack, or by modifying the arguments supplied from the Perl side.
The above is a somewhat simplified view of what really happens. Since Perl allows more flexible calling conventions than C, XSUBs may do much more in practice, such as checking input parameters for validity, throwing exceptions (or returning undef/empty list) if the return value from the C function indicates failure, calling different C functions based on numbers and types of the arguments, providing an object-oriented interface, etc.
Of course, one could write such glue code directly in C. However, this would be a tedious task, especially if one needs to write glue for multiple C functions, and/or one is not familiar enough with the Perl stack discipline and other such arcana.
The
The
A file in
See perlxstut for a tutorial on the whole extension creation process.
Note: For some extensions, Dave Beazley's
On The Road
Many of the examples which follow will concentrate on creating an interface between Perl and the
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
use RPC; $status = rpcb_gettime( "localhost", $timep );
The following
#define PERL_NO_GET_CONTEXT #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 "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()
The Anatomy of an XSUB
The simplest XSUBs consist of 3 parts: a description of the return
value, the name of the The following
double sin(x) double x
Optionally, one can merge the description of types and the list of argument names, rewriting this as
double sin(double x)
This makes this
double sin(double x);
Parameters with C pointer types can have different semantic: C functions with similar declarations
bool string_looks_as_a_number(char *s); bool make_char_uppercase(char *c);
are used in absolutely incompatible manner. Parameters to these functions could be described xsubpp like this:
char * s char &c
Both these
It is convenient to think that the indirection operator "*" should be considered as a part of the type and the address operator "&" should be considered part of the variable. See perlxstypemap for more info about handling qualifiers and unary operators in C types.
The function name and the return type must be placed on separate lines and should be flush left-adjusted.
INCORRECT CORRECT double sin(x) double double x sin(x) double x
The rest of the function description 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 for better readability.
CORRECT double sin(x) double x
More complicated XSUBs may contain many other sections. Each section of an
An
The Argument Stack
The Perl argument stack is used to store the values which are sent as parameters to theXSUBs refer to their stack arguments with the macro
The RETVAL Variable
The If the
If
Older versions of this document recommended to use "void" return value in such cases. It was discovered that this could lead to segfaults in cases when
Returning SVs, AVs and HVs through RETVAL
When you're using
void alpha() PPCODE: ST(0) = newSVpv("Hello World",0); sv_2mortal(ST(0)); XSRETURN(1); SV * beta() CODE: RETVAL = newSVpv("Hello World",0); OUTPUT: RETVAL
This is quite useful as it usually improves readability. While this works fine for an "SV *", it's unfortunately not as easy to have "AV *" or "HV *" as a return value. You should be able to write:
AV * array() CODE: RETVAL = newAV(); /* do something with RETVAL */ OUTPUT: RETVAL
But due to an unfixable bug (fixing it would break lots of existing
AV* T_AVREF_REFCOUNT_FIXED
to get the repaired variant. For backward compatibility with older versions of perl, you can instead decrement the reference count manually when you're returning one of the aforementioned types using "sv_2mortal":
AV * array() CODE: RETVAL = newAV(); sv_2mortal((SV*)RETVAL); /* do something with RETVAL */ OUTPUT: RETVAL
Remember that you don't have to do this for an "SV *". The reference documentation for all core typemaps can be found in perlxstypemap.
The MODULE Keyword
The The following example will start the
MODULE = RPC
The PACKAGE Keyword
When functions within an
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 ]
The same package name can be used more than once, allowing for non-contiguous code. This is useful if you have a stronger ordering principle than package names.
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.
The PREFIX Keyword
The This keyword should follow the
MODULE = RPC PREFIX = rpc_ MODULE = RPC PACKAGE = RPCB PREFIX = rpcb_
The OUTPUT: Keyword
The This keyword will normally be used to complement the
The
bool_t rpcb_gettime(host,timep) char *host time_t &timep OUTPUT: timep
The
bool_t rpcb_gettime(host,timep) char *host time_t &timep OUTPUT: timep sv_setnv(ST(1), (double)timep);
xsubpp emits an automatic "SvSETMAGIC()" for all parameters in the
The NO_OUTPUT Keyword
The With this keyword present ``The
This keyword makes sense only if "RETVAL" is going to be accessed by the user-supplied code. It is especially useful to make a function interface more Perl-like, especially when the C return value is just an error condition indicator. For example,
NO_OUTPUT int delete_file(char *name) POSTCALL: if (RETVAL != 0) croak("Error %d while deleting file '%s'", RETVAL, name);
Here the generated
The CODE: Keyword
This keyword is used in more complicated XSUBs which require
special handling for the C function. The The following
$status = rpcb_gettime( "localhost", $timep );
The
bool_t rpcb_gettime(host,timep) char *host time_t timep CODE: RETVAL = rpcb_gettime( host, &timep ); OUTPUT: timep RETVAL
The INIT: Keyword
The
bool_t rpcb_gettime(host,timep) char *host time_t &timep INIT: printf("# Host is %s\n", host ); OUTPUT: timep
Another use for the
long long lldiv(a,b) long long a long long b INIT: if (a == 0 && b == 0) XSRETURN_UNDEF; if (b == 0) croak("lldiv: cannot divide by 0");
The NO_INIT Keyword
The 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
The TYPEMAP: Keyword
Starting with Perl 5.16, you can embed typemaps into your
TYPEMAP: <<HERE ... your typemap code here ... HERE
where the "TYPEMAP" keyword must appear in the first column of a new line.
Refer to perlxstypemap for details on writing typemaps.
Initializing Function Parameters
C function parameters are normally initialized with their values from the argument stack (which in turn contains the parameters that were passed to theThe following code demonstrates how to supply initialization code for function parameters. The initialization code is eval'ed within double quotes by the compiler before it is added to the output so anything which should be interpreted literally [mainly "$", "@", or "\\"] must be protected with backslashes. The variables $var, $arg, and $type can be used as in typemaps.
bool_t rpcb_gettime(host,timep) char *host = (char *)SvPV_nolen($arg); 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 "=", then it is output in the declaration for the input variable, replacing the initialization supplied by the typemap. If the initialization begins with ";" or "+", then it is performed after all of the input variables have been declared. In the ";" case the initialization normally supplied by the typemap is not performed. For the "+" case, the declaration for the variable will include the initialization from the typemap. A global variable, %v, is available for the truly rare case where information from one initialization is needed in another initialization.
Here's a truly obscure example:
bool_t rpcb_gettime(host,timep) time_t &timep; /* \$v{timep}=@{[$v{timep}=$arg]} */ char *host + SvOK($v{timep}) ? SvPV_nolen($arg) : NULL; OUTPUT: timep
The construct "\$v{timep}=@{[$v{timep}=$arg]}" used in the above example has a two-fold purpose: first, when this line is processed by xsubpp, the Perl snippet "$v{timep}=$arg" is evaluated. Second, the text of the evaluated snippet is output into the generated C file (inside a C comment)! During the processing of "char *host" line, $arg will evaluate to ST(0), and $v{timep} will evaluate to ST(1).
Default Parameter Values
Default values forTo allow the
$status = rpcb_gettime( $timep, $host ); $status = rpcb_gettime( $timep );
The
bool_t rpcb_gettime(timep,host="localhost") char *host time_t timep = NO_INIT CODE: RETVAL = rpcb_gettime( host, &timep ); OUTPUT: timep RETVAL
The PREINIT: Keyword
The If a variable is declared inside a
In such cases, to force an additional variable to be declared together with declarations of other variables, place the declaration into a
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
For this particular case an
bool_t rpcb_gettime(timep) time_t timep = NO_INIT CODE: char *host = "localhost"; RETVAL = rpcb_gettime( host, &timep ); OUTPUT: timep RETVAL
Another way to declare "host" is to use a C block in the
bool_t rpcb_gettime(timep) time_t timep = NO_INIT CODE: { char *host = "localhost"; RETVAL = rpcb_gettime( host, &timep ); } OUTPUT: timep RETVAL
The ability to put additional declarations before the typemap entries are processed is very handy in the cases when typemap conversions manipulate some global state:
MyObject mutate(o) PREINIT: MyState st = global_state; INPUT: MyObject o; CLEANUP: reset_to(global_state, st);
Here we suppose that conversion to "MyObject" in the
There is another way to trade clarity for compactness:
MyObject mutate(o) MyState st = global_state; MyObject o; CLEANUP: reset_to(global_state, st);
and the code for rpcb_gettime() can be rewritten as
bool_t rpcb_gettime(timep) time_t timep = NO_INIT char *host = "localhost"; C_ARGS: host, &timep OUTPUT: timep RETVAL
The SCOPE: Keyword
The To support potentially complex type mappings, if a typemap entry used by an
To enable scoping:
SCOPE: ENABLE
To disable scoping:
SCOPE: DISABLE
The INPUT: Keyword
The The following example shows how the input parameter "timep" can be evaluated late, after a
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
Since
bool_t rpcb_gettime(host,timep) time_t tt; char *host; char *h = host; time_t timep; CODE: RETVAL = rpcb_gettime( h, &tt ); timep = tt; OUTPUT: timep RETVAL
(We used our knowledge that input conversion for "char *" is a ``simple'' one, thus "host" is initialized on the declaration line, and our assignment "h = host" is not performed too early. Otherwise one would need to have the assignment "h = host" in a
The IN/OUTLIST/IN_OUTLIST/OUT/IN_OUT Keywords
In the list of parameters for an Parameters preceded by "OUTLIST"/"IN_OUTLIST"/"OUT"/"IN_OUT" keywords are considered to be used by the C subroutine via pointers. "OUTLIST"/"OUT" keywords indicate that the C subroutine does not inspect the memory pointed by this parameter, but will write through this pointer to provide additional return values.
Parameters preceded by "OUTLIST" keyword do not appear in the usage signature of the generated Perl function.
Parameters preceded by "IN_OUTLIST"/"IN_OUT"/"OUT" do appear as parameters to the Perl function. With the exception of "OUT"-parameters, these parameters are converted to the corresponding C type, then pointers to these data are given as arguments to the C function. It is expected that the C function will write through these pointers.
The return list of the generated Perl function consists of the C return value from the function (unless the
For example, an
void day_month(OUTLIST day, IN unix_time, OUTLIST month) int day int unix_time int month
should be used from Perl as
my ($day, $month) = day_month(time);
The C signature of the corresponding function should be
void day_month(int *day, int unix_time, int *month);
The "IN"/"OUTLIST"/"IN_OUTLIST"/"IN_OUT"/"OUT" keywords can be mixed with ANSI-style declarations, as in
void day_month(OUTLIST int day, int unix_time, OUTLIST int month)
(here the optional "IN" keyword is omitted).
The "IN_OUT" parameters are identical with parameters introduced with ``The & Unary Operator'' and put into the "OUTPUT:" section (see ``The
The "OUTLIST"/"OUT" parameter differ from "IN_OUTLIST"/"IN_OUT" parameters only by the initial value of the Perl parameter not being read (and not being given to the C function - which gets some garbage instead). For example, the same C function as above can be interfaced with as
void day_month(OUT int day, int unix_time, OUT int month);
or
void day_month(day, unix_time, month) int &day = NO_INIT int unix_time int &month = NO_INIT OUTPUT: day month
However, the generated Perl function is called in very C-ish style:
my ($day, $month); day_month($day, time, $month);
The length(NAME) Keyword
If one of the input arguments to the C function is the length of a string argument "NAME", one can substitute the name of the length-argument by "length(NAME)" in the
void dump_chars(char *s, short l) { short n = 0; while (n < l) { printf("s[%d] = \"\\%#03o\"\n", n, (int)s[n]); n++; } } MODULE = x PACKAGE = x void dump_chars(char *s, short length(s))
should be called as "dump_chars($string)".
This directive is supported with ANSI-type function declarations only.
Variable-length Parameter Lists
XSUBs can have variable-length parameter lists by specifying an ellipsis "(...)" in the parameter list. This use of the ellipsis is similar to that found inThe host parameter for the rpcb_gettime()
$status = rpcb_gettime( $timep, $host ); $status = rpcb_gettime( $timep );
The
bool_t rpcb_gettime(timep, ...) time_t timep = NO_INIT PREINIT: char *host = "localhost"; CODE: if( items > 1 ) host = (char *)SvPV_nolen(ST(1)); RETVAL = rpcb_gettime( host, &timep ); OUTPUT: timep RETVAL
The C_ARGS: Keyword
The C_ARGS: keyword allows creating ofFor example, suppose that a 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 "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
symbolic nth_derivative(function, n) symbolic function int n C_ARGS: n, function, default_flags
The PPCODE: Keyword
The The actual difference between
The generated trailer for a
Note that macros ST(i), "XST_m*()" and "XSRETURN*()" work equally well in
The following
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
The
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
Returning Undef And Empty Lists
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
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: if( rpcb_gettime( host, &timep ) ){ ST(0) = sv_newmortal(); sv_setnv( ST(0), (double)timep); } else{ ST(0) = &PL_sv_undef; }
To return an empty list one must use a
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
Since "XSRETURN_*" macros can be used with
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
int rpcb_gettime(host) char *host time_t timep; POSTCALL: if (RETVAL == 0) XSRETURN_UNDEF;
The REQUIRE: Keyword
The
REQUIRE: 1.922
The CLEANUP: Keyword
This keyword can be used when an The POSTCALL: Keyword
This keyword can be used when an See examples in ``The
The
The BOOT: Keyword
The This keyword may be used any time after the first
BOOT: # The following message will be printed when the # bootstrap function executes. printf("Hello from the bootstrap!\n");
The VERSIONCHECK: Keyword
The To enable version checking:
VERSIONCHECK: ENABLE
To disable version checking:
VERSIONCHECK: DISABLE
Note that if the version of the
The PROTOTYPES: Keyword
The To enable prototypes:
PROTOTYPES: ENABLE
To disable prototypes:
PROTOTYPES: DISABLE
The PROTOTYPE: Keyword
This keyword is similar to the
bool_t rpcb_gettime(timep, ...) time_t timep = NO_INIT PROTOTYPE: $;$ PREINIT: char *host = "localhost"; CODE: if( items > 1 ) host = (char *)SvPV_nolen(ST(1)); RETVAL = rpcb_gettime( host, &timep ); OUTPUT: timep RETVAL
If the prototypes are enabled, you can disable it locally for a given
void rpcb_gettime_noproto() PROTOTYPE: DISABLE ...
The ALIAS: Keyword
The The following example will create aliases "FOO::gettime()" and "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
The OVERLOAD: Keyword
Instead of writing an overloaded interface using pure Perl, you
can also use the Since blessed objects are actually stored as
To use the
SV * cmp (lobj, robj, swap) My_Module_obj lobj My_Module_obj robj IV swap OVERLOAD: cmp <=> { /* function defined here */}
In this case, the function will overload both of the three way comparison operators. For all overload operations using non-alpha characters, you must type the parameter without quoting, separating multiple overloads with whitespace. Note that "`` (the stringify overload) should be entered as \''\" (i.e. escaped).
The FALLBACK: Keyword
In addition to the
MODULE = RPC PACKAGE = RPC FALLBACK: TRUE ...
where
The INTERFACE: Keyword
This keyword declares the current 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
symbolic interface_s_ss(arg1, arg2) symbolic arg1 symbolic arg2 INTERFACE: multiply divide add subtract
(This is the complete
The advantage of this approach comparing to
CV *mycv = newXSproto("Symbolic::remainder", XS_Symbolic_interface_s_ss, __FILE__, "$$"); XSINTERFACE_FUNC_SET(mycv, remainder);
say, from another
The INTERFACE_MACRO: Keyword
This keyword allows one to define an The default value is "XSINTERFACE_FUNC" and "XSINTERFACE_FUNC_SET". An
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_ANON(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
The INCLUDE: Keyword
This keyword can be used to pull other files into the The file Rpcb1.xsh contains our "rpcb_gettime()" function:
bool_t rpcb_gettime(host,timep) char *host time_t &timep OUTPUT: timep
The
INCLUDE: Rpcb1.xsh
If the parameters to the
INCLUDE: cat Rpcb1.xsh |
Do not use this to run perl: "INCLUDE: perl |" will run the perl that happens to be the first in your path and not necessarily the same perl that is used to run "xsubpp". See ``The
The INCLUDE_COMMAND: Keyword
Runs the supplied command and includes its output into the current
INCLUDE_COMMAND: cat Rpcb1.xsh INCLUDE_COMMAND: $^X -e ...
The CASE: Keyword
The A
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 EXPORT_XSUB_SYMBOLS: Keyword
The
EXPORT_XSUB_SYMBOLS: ENABLE
in your
EXPORT_XSUB_SYMBOLS: DISABLE
which, again, is the default that you should probably never change. You cannot use this keyword on versions of perl before 5.16 to make XSUBs "static".
The & Unary Operator
The "&" unary operator in theThis is useful to avoid a
The following
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
Inserting POD, Comments and C Preprocessor Directives
C preprocessor directives are allowed within 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.
Using XS With C++
If an If the return type of the
The next examples will use the following C
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 (
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
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
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
color * color::new()
The generated C
RETVAL = new color();
The following is an example of a typemap that could be used for this C
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; }
Interface Strategy
When designing an interface between Perl and a C library a straight translation from C toIdentify 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
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
Identify which values are used by only the C and
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
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.
Perl Objects And C Structures
When dealing with C structures one should select either T_PTROBJ or T_PTRREF for theThe following
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
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 perlxstypemap 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
Safely Storing Static Data in XS
Starting with Perl 5.8, a macro framework has been defined to allow
static data to be safely stored in 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
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.
#define PERL_NO_GET_CONTEXT #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) 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); } OUTPUT: RETVAL char * get_mouse_name(index) int index PREINIT: dMY_CXT; CODE: if (index > MY_CXT.count) croak("There are only 3 blind mice."); else RETVAL = MY_CXT.name[index - 1]; OUTPUT: RETVAL void CLONE(...) CODE: MY_CXT_CLONE;
- MY_CXT_KEY
-
This macro is used to define a unique key to refer to the static data
for an XSmodule. 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_CXTmacro directly after the declaration of "my_cxt_t".
- MY_CXT_INIT
-
The MY_CXT_INITmacro initializes storage for the "my_cxt_t" struct.
It must be called exactly once, typically in a
BOOT:section. If you are maintaining multiple interpreters, it should be called once in each interpreter instance, except for interpreters cloned from existing ones. (But see ``MY_CXT_CLONE''below.) - dMY_CXT
-
Use the dMY_CXT macro (a declaration) in all the functions that access
MY_CXT.
- MY_CXT
-
Use the MY_CXTmacro 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;
- aMY_CXT/pMY_CXT
-
"dMY_CXT" may be quite expensive to calculate, and to avoid the overhead
of invoking it in each function it is possible to pass the declaration
onto other functions using the "aMY_CXT"/"pMY_CXT" macros, eg
void sub1() { dMY_CXT; MY_CXT.index = 1; sub2(aMY_CXT); } void sub2(pMY_CXT) { MY_CXT.index = 2; }
Analogously to "pTHX", there are equivalent forms for when the macro is the first or last in multiple arguments, where an underscore represents a comma, i.e. "_aMY_CXT", "aMY_CXT_", "_pMY_CXT" and "pMY_CXT_".
- MY_CXT_CLONE
- By default, when a new interpreter is created as a copy of an existing one (eg via "threads->create()"), both interpreters share the same physical my_cxt_t structure. Calling "MY_CXT_CLONE" (typically via the package's "CLONE()" function), causes a byte-for-byte copy of the structure to be taken, and any future dMY_CXT will cause the copy to be accessed instead.
- MY_CXT_INIT_INTERP(my_perl)
- dMY_CXT_INTERP(my_perl)
- These are versions of the macros which take an explicit interpreter as an argument.
Note that these macros will only work together within the same source file; that is, a dMY_CTX in one source file will access a different structure than a dMY_CTX in another source file.
Thread-aware system interfaces
Starting from Perl 5.8, in C/CThis wrapping happens always when compiling Perl core source (
EXAMPLES
File "RPC.xs": Interface to some
#define PERL_NO_GET_CONTEXT #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
TYPEMAP Netconfig * T_PTROBJ
File "RPC.pm": Perl module for the
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
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";
CAVEATS
Some modules have an event loop, waiting for user-input. It is highly unlikely that two such modules would work adequately together in a single Perl application.
In general, the perl interpreter views itself as the center of the universe as far as the Perl program goes.
One area where there has been conflict is in regards to C locales. (See perllocale.) perl, with one exception and unless told otherwise, sets up the underlying locale the program is running in to the locale passed into it from the environment. This is an important difference from a generic C language program, where the underlying locale is the ``C'' locale unless the program changes it. As of v5.20, this underlying locale is completely hidden from pure perl code outside the lexical scope of "use locale" except for a couple of function calls in the
To summarize, here's what to expect and how to handle locales in
- Non-locale-aware XScode
-
Keep in mind that even if you think your code is not locale-aware, it
may call a C library function that is. Hopefully the man page for such
a function will indicate that dependency, but the documentation is
imperfect.
The current locale is exposed to
XScode except possibly "LC_NUMERIC" (explained in the next paragraph). There have not been reports of problems with the other categories. Perl initializes things on start-up so that the current locale is the one which is indicated by the user's environment in effect at that time. See ``ENVIRONMENT''in perllocale.However, up through v5.20, Perl initialized things on start-up so that "LC_NUMERIC" was set to the ``C'' locale. But if any code anywhere changed it, it would stay changed. This means that your module can't count on "LC_NUMERIC" being something in particular, and you can't expect floating point numbers (including version strings) to have dots in them. If you don't allow for a non-dot, your code could break if anyone anywhere changed the locale. For this reason, v5.22 changed the behavior so that Perl tries to keep "LC_NUMERIC" in the ``C'' locale except around the operations internally where it should be something else. Misbehaving
XScode will always be able to change the locale anyway, but the most common instance of this is checked for and handled. - Locale-aware XScode
-
If the locale from the user's environment is desired, there should be no
need for XScode to set the locale except for "LC_NUMERIC", as perl has already set it up.XScode should avoid changing the locale, as it can adversely affect other, unrelated, code and may not be thread safe. However, some alien libraries that may be called do set it, such as "Gtk". This can cause problems for the perl core and other modules. Starting in v5.20.1, calling the function sync_locale() fromXSshould be sufficient to avoid most of these problems. Prior to this, you need a pure Perl statement that does this:
POSIX::setlocale(LC_ALL, POSIX::setlocale(LC_ALL));
In the event that your
XScode may need the underlying "LC_NUMERIC" locale, there are macros available to access this; see ``Locale-related functions and macros'' in perlapi.
XS VERSION
This document covers features supported by "ExtUtils::ParseXS" (also known as "xsubpp") 3.13_01.AUTHOR
Originally written by Dean Roehrich <roehrich@cray.com>.Maintained since 1996 by The Perl Porters <perlbug@perl.org>.