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 Returning SVs, AVs and HVs through RETVAL
+
+When you're using RETVAL to return an C<SV *>, there's some magic
+going on behind the scenes that should be mentioned. When you're
+manipulating the argument stack using the ST(x) macro, for example,
+you usually have to pay special attention to reference counts. (For
+more about reference counts, see L<perlguts>.) To make your life
+easier, the typemap file automatically makes C<RETVAL> mortal when
+you're returning an C<SV *>. Thus, the following two XSUBs are more
+or less equivalent:
+
+ 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 C<SV *>, it's unfortunately not as easy
+to have C<AV *> or C<HV *> as a return value. You I<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
+CPAN modules) in the typemap file, the reference count of the C<AV *>
+is not properly decremented. Thus, the above XSUB would leak memory
+whenever it is being called. The same problem exists for C<HV *>.
+
+When you're returning an C<AV *> or a C<HV *>, you have make sure
+their reference count is decremented by making the AV or HV mortal:
+
+ AV *
+ array()
+ CODE:
+ RETVAL = newAV();
+ sv_2mortal((SV*)RETVAL);
+ /* do something with RETVAL */
+ OUTPUT:
+ RETVAL
+
+And also remember that you don't have to do this for an C<SV *>.
+
=head2 The MODULE Keyword
The MODULE keyword is used to start the XS code and to specify the package
is quietly ignored.
The following code demonstrates how to supply initialization code for
-function parameters. The initialization code is eval'd within double
+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 C<$>, C<@>, or C<\\>]
must be protected with backslashes. The variables $var, $arg,
bool_t
rpcb_gettime(host,timep)
- char *host = (char *)SvPV($arg,PL_na);
+ char *host = (char *)SvPV_nolen($arg);
time_t &timep = 0;
OUTPUT:
timep
bool_t
rpcb_gettime(host,timep)
- time_t &timep ; /* \$v{timep}=@{[$v{timep}=$arg]} */
- char *host + SvOK($v{timep}) ? SvPV($arg,PL_na) : NULL;
+ time_t &timep; /* \$v{timep}=@{[$v{timep}=$arg]} */
+ char *host + SvOK($v{timep}) ? SvPV_nolen($arg) : NULL;
OUTPUT:
timep
If one of the input arguments to the C function is the length of a string
argument C<NAME>, one can substitute the name of the length-argument by
-C<length(NAME)> in the XSUB declaration. This argument must be omited when
+C<length(NAME)> in the XSUB declaration. This argument must be omitted when
the generated Perl function is called. E.g.,
void
time_t timep = NO_INIT
PREINIT:
char *host = "localhost";
- STRLEN n_a;
CODE:
if( items > 1 )
- host = (char *)SvPV(ST(1), n_a);
+ host = (char *)SvPV_nolen(ST(1));
RETVAL = rpcb_gettime( host, &timep );
OUTPUT:
timep
time_t timep;
bool_t x;
CODE:
- ST(0) = sv_newmortal();
if( rpcb_gettime( host, &timep ) ){
+ ST(0) = sv_newmortal();
sv_setnv( ST(0), (double)timep);
}
else{
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.
+the XSUB stack is properly adjusted. Consult L<perlapi> for other
+C<XSRETURN> macros.
Since C<XSRETURN_*> macros can be used with CODE blocks as well, one can
rewrite this example as:
PROTOTYPE: $;$
PREINIT:
char *host = "localhost";
- STRLEN n_a;
CODE:
if( items > 1 )
- host = (char *)SvPV(ST(1), n_a);
+ host = (char *)SvPV_nolen(ST(1));
RETVAL = rpcb_gettime( host, &timep );
OUTPUT:
timep
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, seperating
+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).
C<subtract_off>. Then one can use
#define XSINTERFACE_FUNC_BYOFFSET(ret,cv,f) \
- ((XSINTERFACE_CVT(ret,))fp[CvXSUBANY(cv).any_i32])
+ ((XSINTERFACE_CVT_ANON(ret))fp[CvXSUBANY(cv).any_i32])
#define XSINTERFACE_FUNC_BYOFFSET_set(cv,f) \
CvXSUBANY(cv).any_i32 = CAT2( f, _off )
T_PTROBJ_SPECIAL
if (sv_derived_from($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")) {
IV tmp = SvIV((SV*)SvRV($arg));
- $var = ($type) tmp;
+ $var = INT2PTR($type, tmp);
}
else
croak(\"$var is not of type ${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")
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.
+
=head2 Safely Storing Static Data in XS
Starting with Perl 5.8, a macro framework has been defined to allow
dMY_CXT;
CODE:
if (MY_CXT.count >= 3) {
- warn("Already have 3 blind mice") ;
+ warn("Already have 3 blind mice");
RETVAL = 0;
}
else {
else
RETVAL = newSVpv(MY_CXT.name[index - 1]);
+ void
+ CLONE(...)
+ CODE:
+ MY_CXT_CLONE;
B<REFERENCE>
The MY_CXT_INIT macro initialises storage for the C<my_cxt_t> struct.
-It I<must> be called exactly once -- typically in a BOOT: section.
+It I<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 C<MY_CXT_CLONE> below.)
=item dMY_CXT
dMY_CXT;
MY_CXT.index = 2;
+=item aMY_CXT/pMY_CXT
+
+C<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 C<aMY_CXT>/C<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 C<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. C<_aMY_CXT>, C<aMY_CXT_>, C<_pMY_CXT> and C<pMY_CXT_>.
+
+=item MY_CXT_CLONE
+
+By default, when a new interpreter is created as a copy of an existing one
+(eg via C<< threads->create() >>), both interpreters share the same physical
+my_cxt_t structure. Calling C<MY_CXT_CLONE> (typically via the package's
+C<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.
+
+=item MY_CXT_INIT_INTERP(my_perl)
+
+=item dMY_CXT_INTERP(my_perl)
+
+These are versions of the macros which take an explicit interpreter as an
+argument.
+
=back
+Note that these macros will only work together within the I<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.
+
+=head2 Thread-aware system interfaces
+
+Starting from Perl 5.8, in C/C++ level Perl knows how to wrap
+system/library interfaces that have thread-aware versions
+(e.g. getpwent_r()) into frontend macros (e.g. getpwent()) that
+correctly handle the multithreaded interaction with the Perl
+interpreter. This will happen transparently, the only thing
+you need to do is to instantiate a Perl interpreter.
+
+This wrapping happens always when compiling Perl core source
+(PERL_CORE is defined) or the Perl core extensions (PERL_EXT is
+defined). When compiling XS code outside of Perl core the wrapping
+does not take place. Note, however, that intermixing the _r-forms
+(as Perl compiled for multithreaded operation will do) and the _r-less
+forms is neither well-defined (inconsistent results, data corruption,
+or even crashes become more likely), nor is it very portable.
+
=head1 EXAMPLES
File C<RPC.xs>: Interface to some ONC+ RPC bind library functions.