From 7b22950dc52818f7ed2f9fd6e43f824152e48687 Mon Sep 17 00:00:00 2001 From: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon, 30 Sep 2019 11:12:18 -0400 Subject: [PATCH] Package init --- ExtUtils-ParseXS-3.35-Upgrade-to-3.39.patch | 4743 +++++++++++++++++++ ExtUtils-ParseXS-3.35.tar.gz | Bin 0 -> 68623 bytes perl-ExtUtils-ParseXS.spec | 61 + 3 files changed, 4804 insertions(+) create mode 100644 ExtUtils-ParseXS-3.35-Upgrade-to-3.39.patch create mode 100644 ExtUtils-ParseXS-3.35.tar.gz create mode 100644 perl-ExtUtils-ParseXS.spec diff --git a/ExtUtils-ParseXS-3.35-Upgrade-to-3.39.patch b/ExtUtils-ParseXS-3.35-Upgrade-to-3.39.patch new file mode 100644 index 0000000..a18bfae --- /dev/null +++ b/ExtUtils-ParseXS-3.35-Upgrade-to-3.39.patch @@ -0,0 +1,4743 @@ +From c85261a4cef59150c379ff88a21d0f9ca6374dc2 Mon Sep 17 00:00:00 2001 +From: Jitka Plesnikova +Date: Thu, 24 May 2018 09:57:37 +0200 +Subject: [PATCH] Upgrade to 3.39 + +--- + Changes | 6 + + lib/ExtUtils/ParseXS.pm | 14 +- + lib/ExtUtils/ParseXS/Constants.pm | 2 +- + lib/ExtUtils/ParseXS/CountLines.pm | 2 +- + lib/ExtUtils/ParseXS/Eval.pm | 6 +- + lib/ExtUtils/ParseXS/Utilities.pm | 2 +- + lib/ExtUtils/Typemaps.pm | 6 +- + lib/ExtUtils/Typemaps/Cmd.pm | 2 +- + lib/ExtUtils/Typemaps/InputMap.pm | 2 +- + lib/ExtUtils/Typemaps/OutputMap.pm | 2 +- + lib/ExtUtils/Typemaps/Type.pm | 2 +- + lib/perlxs.pod | 2354 ++++++++++++++++++++++++++++++++++++ + lib/perlxstut.pod | 1401 +++++++++++++++++++++ + lib/perlxstypemap.pod | 711 +++++++++++ + t/XSTest.xs | 1 + + t/XSUsage.xs | 2 + + 16 files changed, 4497 insertions(+), 18 deletions(-) + create mode 100644 lib/perlxs.pod + create mode 100644 lib/perlxstut.pod + create mode 100644 lib/perlxstypemap.pod + +diff --git a/Changes b/Changes +index 0181371..f9fb36e 100644 +--- a/Changes ++++ b/Changes +@@ -1,5 +1,11 @@ + Revision history for Perl extension ExtUtils::ParseXS. + ++3.36 ++ - Make generated code avoid warnings about the "items" variable ++ being unused ++ - Avoid some unused-variable warnings generated by XS code in the ++ test suite ++ + 3.35 - Mon Jul 31 17:50:00 CET 2017 + - Fix ExtUtils-ParseXS/t/*.t that needed '.' in @INC (David Mitchell) + - Remove impediment to compiling under C++11 (Karl Williamson) +diff --git a/lib/ExtUtils/ParseXS.pm b/lib/ExtUtils/ParseXS.pm +index d629cf6..e1f0940 100644 +--- a/lib/ExtUtils/ParseXS.pm ++++ b/lib/ExtUtils/ParseXS.pm +@@ -11,12 +11,12 @@ use Symbol; + + our $VERSION; + BEGIN { +- $VERSION = '3.35'; ++ $VERSION = '3.39'; ++ require ExtUtils::ParseXS::Constants; ExtUtils::ParseXS::Constants->VERSION($VERSION); ++ require ExtUtils::ParseXS::CountLines; ExtUtils::ParseXS::CountLines->VERSION($VERSION); ++ require ExtUtils::ParseXS::Utilities; ExtUtils::ParseXS::Utilities->VERSION($VERSION); ++ require ExtUtils::ParseXS::Eval; ExtUtils::ParseXS::Eval->VERSION($VERSION); + } +-use ExtUtils::ParseXS::Constants $VERSION; +-use ExtUtils::ParseXS::CountLines $VERSION; +-use ExtUtils::ParseXS::Utilities $VERSION; +-use ExtUtils::ParseXS::Eval $VERSION; + $VERSION = eval $VERSION if $VERSION =~ /_/; + + use ExtUtils::ParseXS::Utilities qw( +@@ -519,9 +519,10 @@ EOF + EOF + } + else { +- # cv likely to be unused ++ # cv and items likely to be unused + print Q(<<"EOF"); + # PERL_UNUSED_VAR(cv); /* -W */ ++# PERL_UNUSED_VAR(items); /* -W */ + EOF + } + +@@ -871,6 +872,7 @@ EOF + #XS_EUPXS(XS_$self->{Packid}_nil) + #{ + # dXSARGS; ++# PERL_UNUSED_VAR(items); + # XSRETURN_EMPTY; + #} + # +diff --git a/lib/ExtUtils/ParseXS/Constants.pm b/lib/ExtUtils/ParseXS/Constants.pm +index 2150fb8..45b5674 100644 +--- a/lib/ExtUtils/ParseXS/Constants.pm ++++ b/lib/ExtUtils/ParseXS/Constants.pm +@@ -3,7 +3,7 @@ use strict; + use warnings; + use Symbol; + +-our $VERSION = '3.35'; ++our $VERSION = '3.39'; + + =head1 NAME + +diff --git a/lib/ExtUtils/ParseXS/CountLines.pm b/lib/ExtUtils/ParseXS/CountLines.pm +index ad86b57..5b48449 100644 +--- a/lib/ExtUtils/ParseXS/CountLines.pm ++++ b/lib/ExtUtils/ParseXS/CountLines.pm +@@ -1,7 +1,7 @@ + package ExtUtils::ParseXS::CountLines; + use strict; + +-our $VERSION = '3.35'; ++our $VERSION = '3.39'; + + our $SECTION_END_MARKER; + +diff --git a/lib/ExtUtils/ParseXS/Eval.pm b/lib/ExtUtils/ParseXS/Eval.pm +index 6b06bf5..9eba5e5 100644 +--- a/lib/ExtUtils/ParseXS/Eval.pm ++++ b/lib/ExtUtils/ParseXS/Eval.pm +@@ -2,7 +2,7 @@ package ExtUtils::ParseXS::Eval; + use strict; + use warnings; + +-our $VERSION = '3.35'; ++our $VERSION = '3.39'; + + =head1 NAME + +@@ -29,7 +29,7 @@ Warns the contents of C<$@> if any. + Not all these variables are necessarily considered "public" wrt. use in + typemaps, so beware. Variables set up from the ExtUtils::ParseXS object: + +- $Package $Alias $func_name $Full_func_name $pname ++ $Package $ALIAS $func_name $Full_func_name $pname + + Variables set up from C<$other_hashref>: + +@@ -63,7 +63,7 @@ Warns the contents of C<$@> if any. + Not all these variables are necessarily considered "public" wrt. use in + typemaps, so beware. Variables set up from the ExtUtils::ParseXS object: + +- $Package $Alias $func_name $Full_func_name $pname ++ $Package $ALIAS $func_name $Full_func_name $pname + + Variables set up from C<$other_hashref>: + +diff --git a/lib/ExtUtils/ParseXS/Utilities.pm b/lib/ExtUtils/ParseXS/Utilities.pm +index bc1e098..ae25b33 100644 +--- a/lib/ExtUtils/ParseXS/Utilities.pm ++++ b/lib/ExtUtils/ParseXS/Utilities.pm +@@ -5,7 +5,7 @@ use Exporter; + use File::Spec; + use ExtUtils::ParseXS::Constants (); + +-our $VERSION = '3.35'; ++our $VERSION = '3.39'; + + our (@ISA, @EXPORT_OK); + @ISA = qw(Exporter); +diff --git a/lib/ExtUtils/Typemaps.pm b/lib/ExtUtils/Typemaps.pm +index 992d15b..a762322 100644 +--- a/lib/ExtUtils/Typemaps.pm ++++ b/lib/ExtUtils/Typemaps.pm +@@ -2,7 +2,7 @@ package ExtUtils::Typemaps; + use 5.006001; + use strict; + use warnings; +-our $VERSION = '3.35'; ++our $VERSION = '3.38'; + + require ExtUtils::ParseXS; + require ExtUtils::ParseXS::Constants; +@@ -781,7 +781,9 @@ corresponding OUTPUT code: + $var.context.value().size()); + ', + 'T_OUT' => ' { +- GV *gv = newGVgen("$Package"); ++ GV *gv = (GV *)sv_newmortal(); ++ gv_init_pvn(gv, gv_stashpvs("$Package",1), ++ "__ANONIO__",10,0); + if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) ) + sv_setsv( + $arg, +diff --git a/lib/ExtUtils/Typemaps/Cmd.pm b/lib/ExtUtils/Typemaps/Cmd.pm +index 7ff0780..3c33f54 100644 +--- a/lib/ExtUtils/Typemaps/Cmd.pm ++++ b/lib/ExtUtils/Typemaps/Cmd.pm +@@ -2,7 +2,7 @@ package ExtUtils::Typemaps::Cmd; + use 5.006001; + use strict; + use warnings; +-our $VERSION = '3.35'; ++our $VERSION = '3.38'; + + use ExtUtils::Typemaps; + +diff --git a/lib/ExtUtils/Typemaps/InputMap.pm b/lib/ExtUtils/Typemaps/InputMap.pm +index b626973..bf19df1 100644 +--- a/lib/ExtUtils/Typemaps/InputMap.pm ++++ b/lib/ExtUtils/Typemaps/InputMap.pm +@@ -2,7 +2,7 @@ package ExtUtils::Typemaps::InputMap; + use 5.006001; + use strict; + use warnings; +-our $VERSION = '3.35'; ++our $VERSION = '3.38'; + + =head1 NAME + +diff --git a/lib/ExtUtils/Typemaps/OutputMap.pm b/lib/ExtUtils/Typemaps/OutputMap.pm +index 8c72e5b..90adb48 100644 +--- a/lib/ExtUtils/Typemaps/OutputMap.pm ++++ b/lib/ExtUtils/Typemaps/OutputMap.pm +@@ -2,7 +2,7 @@ package ExtUtils::Typemaps::OutputMap; + use 5.006001; + use strict; + use warnings; +-our $VERSION = '3.35'; ++our $VERSION = '3.38'; + + =head1 NAME + +diff --git a/lib/ExtUtils/Typemaps/Type.pm b/lib/ExtUtils/Typemaps/Type.pm +index 7909bbe..01bd51d 100644 +--- a/lib/ExtUtils/Typemaps/Type.pm ++++ b/lib/ExtUtils/Typemaps/Type.pm +@@ -4,7 +4,7 @@ use strict; + use warnings; + require ExtUtils::Typemaps; + +-our $VERSION = '3.35'; ++our $VERSION = '3.38'; + + =head1 NAME + +diff --git a/lib/perlxs.pod b/lib/perlxs.pod +new file mode 100644 +index 0000000..1419ee0 +--- /dev/null ++++ b/lib/perlxs.pod +@@ -0,0 +1,2354 @@ ++=head1 NAME ++ ++perlxs - XS language reference manual ++ ++=head1 DESCRIPTION ++ ++=head2 Introduction ++ ++XS is an interface description file format used to create an extension ++interface between Perl and C code (or a C library) which one wishes ++to use with Perl. The XS interface is combined with the library to ++create a new library which can then be either dynamically loaded ++or statically linked into perl. The XS interface description is ++written in the XS language and is the core component of the Perl ++extension interface. ++ ++Before writing XS, read the L section below. ++ ++An B forms the basic unit of the XS interface. After compilation ++by the B compiler, each XSUB amounts to a C function definition ++which will provide the glue between Perl calling conventions and C ++calling conventions. ++ ++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. XS comes to the rescue here: ++instead of writing this glue C code in long-hand, one can write ++a more concise short-hand I of what should be done by ++the glue, and let the XS compiler B handle the rest. ++ ++The XS language allows one to describe the mapping between how the C ++routine is used, and how the corresponding Perl routine is used. It ++also allows creation of Perl routines which are directly translated to ++C code and which are not related to a pre-existing C function. In cases ++when the C interface coincides with the Perl interface, the XSUB ++declaration is almost identical to a declaration of a C function (in K&R ++style). In such circumstances, there is another tool called C ++that is able to translate an entire C header file into a corresponding ++XS file that will provide glue to the functions/macros described in ++the header file. ++ ++The XS compiler is called B. This compiler creates ++the constructs necessary to let an XSUB manipulate Perl values, and ++creates the glue necessary to let Perl call the XSUB. The compiler ++uses B to determine how to map C function parameters ++and output values to Perl values and back. The default typemap ++(which comes with Perl) handles many common C types. A supplementary ++typemap may also be needed to handle any special structures and types ++for the library being linked. For more information on typemaps, ++see L. ++ ++A file in XS format starts with a C language section which goes until the ++first C> directive. Other XS directives and XSUB definitions ++may follow this line. The "language" used in this part of the file ++is usually referred to as the XS language. B recognizes and ++skips POD (see L) in both the C and XS language sections, which ++allows the XS file to contain embedded documentation. ++ ++See L for a tutorial on the whole extension creation process. ++ ++Note: For some extensions, Dave Beazley's SWIG system may provide a ++significantly more convenient mechanism for creating the extension ++glue code. See L 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 ++ 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, C, and C, will always be present at the ++beginning of an XS file. This approach and others will be ++expanded later in this document. A #define for C ++should be present to fetch the interpreter context more efficiently, ++see L for details. ++ ++ #define PERL_NO_GET_CONTEXT ++ #include "EXTERN.h" ++ #include "perl.h" ++ #include "XSUB.h" ++ #include ++ ++ 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 ++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 simplest XSUBs consist of 3 parts: a description of the return ++value, the name of the XSUB routine and the names of its arguments, ++and a description of types or formats of the arguments. ++ ++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 ++ ++Optionally, one can merge the description of types and the list of ++argument names, rewriting this as ++ ++ double ++ sin(double x) ++ ++This makes this XSUB look similar to an ANSI C declaration. An optional ++semicolon is allowed after the argument list, as in ++ ++ 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 B like this: ++ ++ char * s ++ char &c ++ ++Both these XS declarations correspond to the C C type, but they have ++different semantics, see L<"The & Unary Operator">. ++ ++It is convenient to think that the indirection operator ++C<*> should be considered as a part of the type and the address operator C<&> ++should be considered part of the variable. See L ++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 XSUB starts with the corresponding keyword, such as INIT: or CLEANUP:. ++However, the first two lines of an XSUB always contain the same data: ++descriptions of the return type and the names of the function and its ++parameters. Whatever immediately follows these is considered to be ++an INPUT: section unless explicitly marked with another keyword. ++(See L.) ++ ++An XSUB section continues until another section-start keyword is found. ++ ++=head2 The Argument Stack ++ ++The Perl argument stack is used to store the values which are ++sent as parameters to the XSUB and to store the XSUB's ++return value(s). In reality all Perl functions (including non-XSUB ++ones) keep their values on this stack all 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, where I ++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 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 special C variable that is declared automatically ++for you. The C type of RETVAL matches the return type of the C library ++function. The B compiler will declare this variable in each XSUB ++with non-C return type. By default the generated C function ++will use RETVAL 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 then the compiler will ++not declare a RETVAL variable for that function. When using ++a PPCODE: section no manipulation of the RETVAL variable is required, the ++section may use direct stack manipulation to place output values on the stack. ++ ++If PPCODE: directive is not used, C return value should be used ++only for subroutines which do not return a value, I CODE: ++directive is used which sets ST(0) explicitly. ++ ++Older versions of this document recommended to use C return ++value in such cases. It was discovered that this could lead to ++segfaults in cases when XSUB was I C. This practice is ++now deprecated, and may be not supported at some future version. Use ++the return value C in such cases. (Currently C 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 as return value.) ++ ++=head2 Returning SVs, AVs and HVs through RETVAL ++ ++When you're using RETVAL to return an C, 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.) To make your life ++easier, the typemap file automatically makes C mortal when ++you're returning an C. 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, it's unfortunately not as easy ++to have C or C as a return value. You I 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 ++is not properly decremented. Thus, the above XSUB would leak memory ++whenever it is being called. The same problem exists for C, ++C, and C (which indicates a scalar reference, not ++a general C). ++In XS code on perls starting with perl 5.16, you can override the ++typemaps for any of these types with a version that has proper ++handling of refcounts. In your C section, do ++ ++ 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 C: ++ ++ 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 C. The reference ++documentation for all core typemaps can be found in L. ++ ++=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 with ++POD stripped, but otherwise 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 ] ++ ++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. ++ ++=head2 The PREFIX Keyword ++ ++The PREFIX keyword designates prefixes which should be ++removed from the Perl function names. If the C function is ++C and the PREFIX value is C then Perl will ++see this function as C. ++ ++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 which have no CODE: or PPCODE: section, ++such as the sin() function above, the RETVAL variable is ++automatically designated as an output value. For more complex functions ++the B 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 emits an automatic C 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 line ++to disable it for the remainder of the parameters in the OUTPUT section. ++Likewise, C can be used to reenable it for the ++remainder of the OUTPUT section. See L for more details ++about 'set' magic. ++ ++=head2 The NO_OUTPUT Keyword ++ ++The NO_OUTPUT can be placed as the first token of the XSUB. This keyword ++indicates that while the C subroutine we provide an interface to has ++a non-C return type, the return value of this C subroutine should not ++be returned from the generated Perl subroutine. ++ ++With this keyword present L is created, and in the ++generated call to the subroutine this variable is assigned to, but the value ++of this variable is not going to be used in the auto-generated code. ++ ++This keyword makes sense only if C 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 XS function returns nothing on success, and will die() ++with a meaningful error message on error. ++ ++=head2 The CODE: Keyword ++ ++This keyword is used in more complicated XSUBs which require ++special handling for the C function. The RETVAL variable is ++still declared, but it will not be returned unless it is specified ++in the OUTPUT: section. ++ ++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 ++ ++Another use for the INIT: section is to check for preconditions before ++making a call to the C function: ++ ++ 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"); ++ ++=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 ++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 The TYPEMAP: Keyword ++ ++Starting with Perl 5.16, you can embed typemaps into your XS code ++instead of or in addition to typemaps in a separate file. Multiple ++such embedded typemaps will be processed in order of appearance in ++the XS code and like local typemap files take precedence over the ++default typemap, the embedded typemaps may overwrite previous ++definitions of TYPEMAP, INPUT, and OUTPUT stanzas. The syntax for ++embedded typemaps is ++ ++ TYPEMAP: < keyword must appear in the first column of a ++new line. ++ ++Refer to L for details on writing typemaps. ++ ++=head2 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 the XSUB from Perl). The typemaps contain the ++code segments which are used to translate the Perl values to ++the C parameters. The programmer, however, is allowed to ++override the typemaps and supply alternate (or additional) ++initialization code. Initialization code starts with the first ++C<=>, C<;> or C<+> on a line in the INPUT: section. The only ++exception happens if this C<;> terminates the line, then this C<;> ++is quietly ignored. ++ ++The 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 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_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 C<=>, then it is output in ++the declaration for the input variable, replacing the initialization ++supplied by the typemap. If the initialization ++begins with C<;> or C<+>, then it is performed after ++all of the input variables have been declared. In the C<;> ++case the initialization normally supplied by the typemap is not performed. ++For the C<+> case, the declaration for the variable will include the ++initialization from the typemap. A global ++variable, C<%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 C<\$v{timep}=@{[$v{timep}=$arg]}> used in the above ++example has a two-fold purpose: first, when this line is processed by ++B, the Perl snippet C<$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 C line, ++C<$arg> will evaluate to C, and C<$v{timep}> will evaluate to ++C. ++ ++=head2 Default Parameter Values ++ ++Default values for XSUB arguments can be specified by placing an ++assignment statement in the parameter list. The default value may ++be a number, a string or the special string C. 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. This XSUB can be called ++from Perl 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 immediately ++before or after the declarations of the parameters from the INPUT: section ++are emitted. ++ ++If a variable is declared inside a CODE: section it will follow any typemap ++code that is emitted for the input parameters. This may result in the ++declaration ending up after C code, which is C syntax error. Similar ++errors may happen with an explicit C<;>-type or C<+>-type initialization of ++parameters is used (see L<"Initializing Function Parameters">). Declaring ++these variables in an INIT: section will not help. ++ ++In such cases, to force an additional variable to be declared together ++with declarations of other variables, place the declaration into a ++PREINIT: section. 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 ++ ++For this particular case an INIT: keyword would generate the ++same C code as the PREINIT: keyword. Another 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 ++ ++Another way to declare C is to use a C block in the CODE: section: ++ ++ 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 C in the INPUT: section and from ++MyObject when processing RETVAL will modify a global variable C. ++After these conversions are performed, we restore the old value of ++C (to avoid memory leaks, for example). ++ ++There is another way to trade clarity for compactness: INPUT sections allow ++declaration of C variables which do not appear in the parameter list of ++a subroutine. Thus the above code for mutate() can be rewritten as ++ ++ 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 ++ ++=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 an XSUB contains a comment like C then scoping will ++be automatically 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 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 ++ ++Since INPUT sections allow declaration of C variables which do not appear ++in the parameter list of a subroutine, this may be shortened to: ++ ++ 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 C is a "simple" one, ++thus C is initialized on the declaration line, and our assignment ++C is not performed too early. Otherwise one would need to have the ++assignment C in a CODE: or INIT: section.) ++ ++=head2 The IN/OUTLIST/IN_OUTLIST/OUT/IN_OUT Keywords ++ ++In the list of parameters for an XSUB, one can precede parameter names ++by the C/C/C/C/C keywords. ++C keyword is the default, the other keywords indicate how the Perl ++interface should differ from the C interface. ++ ++Parameters preceded by C/C/C/C ++keywords are considered to be used by the C subroutine I. C/C 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 C keyword do not appear in the usage ++signature of the generated Perl function. ++ ++Parameters preceded by C/C/C I appear as ++parameters to the Perl function. With the exception of ++C-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 XSUB is of C return type or ++C was used) followed by all the C ++and C parameters (in the order of appearance). On the ++return from the XSUB the C/C Perl parameter will be ++modified to have the values written by the C function. ++ ++For example, an XSUB ++ ++ 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 C/C/C/C/C 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 C keyword is omitted). ++ ++The C parameters are identical with parameters introduced with ++L and put into the C section (see ++L). The C parameters are very similar, ++the only difference being that the value C function writes through the ++pointer would not modify the Perl parameter, but is put in the output ++list. ++ ++The C/C parameter differ from C/C ++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); ++ ++=head2 The C Keyword ++ ++If one of the input arguments to the C function is the length of a string ++argument C, one can substitute the name of the length-argument by ++C in the XSUB declaration. This argument must be omitted when ++the generated Perl function is called. E.g., ++ ++ 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 C. ++ ++This directive is supported with ANSI-type function declarations only. ++ ++=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 variable which the ++B 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 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"; ++ CODE: ++ if( items > 1 ) ++ host = (char *)SvPV_nolen(ST(1)); ++ 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 PPCODE: 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 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 ++C. 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 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 should not be used ++together within the same XSUB. ++ ++The actual difference between PPCODE: and CODE: sections is in the ++initialization of C macro (which stands for the I Perl ++stack pointer), and in the handling of data on the stack when returning ++from an XSUB. In CODE: sections SP preserves the value which was on ++entry to the XSUB: SP is on the function pointer (which follows the ++last parameter). In PPCODE: sections SP is moved backward to the ++beginning of the parameter list, which allows C macros ++to place output values in the place Perl expects them to be when ++the XSUB returns back to Perl. ++ ++The generated trailer for a CODE: section ensures that the number of return ++values Perl will see is either 0 or 1 (depending on the Cness of the ++return value of the C function, and heuristics mentioned in ++L<"The RETVAL Variable">). The trailer generated for a PPCODE: section ++is based on the number of return values and on the number of times ++C was updated by C<[X]PUSH*()> macros. ++ ++Note that macros C, C and C work equally ++well in CODE: sections and PPCODE: sections. ++ ++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 return type for this function tells the B 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 compiler to create a stack pointer available as C, 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 for details about 'set' magic. ++ ++=head2 Returning Undef And Empty Lists ++ ++Occasionally the programmer will want to return simply ++C 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 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: ++ 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 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 in the above ++XSUB, rather than letting control fall through to the end. In those ++situations C should be used, instead. This will ensure that ++the XSUB stack is properly adjusted. Consult L for other ++C macros. ++ ++Since C macros can be used with CODE blocks as well, one can ++rewrite this example as: ++ ++ int ++ rpcb_gettime(host) ++ char *host ++ PREINIT: ++ time_t timep; ++ CODE: ++ RETVAL = rpcb_gettime( host, &timep ); ++ if (RETVAL == 0) ++ XSRETURN_UNDEF; ++ OUTPUT: ++ RETVAL ++ ++In fact, one can put this check into a POSTCALL: section as well. Together ++with PREINIT: simplifications, this leads to: ++ ++ int ++ rpcb_gettime(host) ++ char *host ++ time_t timep; ++ POSTCALL: ++ if (RETVAL == 0) ++ XSRETURN_UNDEF; ++ ++=head2 The REQUIRE: Keyword ++ ++The REQUIRE: keyword is used to indicate the minimum version of the ++B compiler needed to compile the XS module. An XS module which ++contains the following statement will compile with only B 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:, 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 POSTCALL: Keyword ++ ++This keyword can be used when an XSUB requires special procedures ++executed after the C subroutine call is performed. When the POSTCALL: ++keyword is used it must precede OUTPUT: and CLEANUP: blocks which are ++present in the XSUB. ++ ++See examples in L<"The NO_OUTPUT Keyword"> and L<"Returning Undef And Empty Lists">. ++ ++The POSTCALL: block does not make a lot of sense when the C subroutine ++call is supplied by user by providing either CODE: or PPCODE: section. ++ ++=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 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'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 ++ ++Note that if the version of the PM module is an NV (a floating point ++number), it will be stringified with a possible loss of precision ++(currently chopping to nine decimal places) so that it may not match ++the version of the XS module anymore. Quoting the $VERSION declaration ++to make it a string is recommended if long version numbers are used. ++ ++=head2 The PROTOTYPES: Keyword ++ ++The PROTOTYPES: keyword corresponds to B's C<-prototypes> and ++C<-noprototypes> options. This keyword overrides the command line options. ++Prototypes are disabled 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. ++Note that B will nag you if you don't explicitly enable or disable ++prototypes, with: ++ ++ Please specify prototyping behavior for Foo.xs (see perlxs manual) ++ ++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 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 for information about Perl ++prototypes. ++ ++ 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 ++XSUB as in the following example: ++ ++ void ++ rpcb_gettime_noproto() ++ PROTOTYPE: DISABLE ++ ... ++ ++=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 which contain the ++index of the alias which was used. When the XSUB is called with its ++declared name C will be 0. ++ ++The following example will create aliases C and ++C 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 OVERLOAD: Keyword ++ ++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 in such a way as to accept the number ++of parameters supplied by perl's overload system. For most overload ++methods, it will be three parameters; for the C function it will ++be four. However, the bitwise operators C<&>, C<|>, C<^>, and C<~> may be ++called with three I five arguments (see L). ++ ++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: ++ ++ 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). ++ ++Since, as mentioned above, bitwise operators may take extra arguments, you ++may want to use something like C<(lobj, robj, swap, ...)> (with ++literal C<...>) as your parameter list. ++ ++=head2 The FALLBACK: Keyword ++ ++In addition to the OVERLOAD keyword, if you need to control how ++Perl autogenerates missing overloaded operators, you can set the ++FALLBACK keyword in the module header section, like this: ++ ++ MODULE = RPC PACKAGE = RPC ++ ++ FALLBACK: TRUE ++ ... ++ ++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 ++L for more details. ++ ++=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 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 ++C, see the next section.) ++ ++=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, ++and C for this C. The setter macro is given cv, ++and the function pointer. ++ ++The default value is C and C. ++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 with offsets being C, C, C, ++C. 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 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 contains our C 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. This feature is ++mildly deprecated in favour of the C directive, as documented ++below. ++ ++ INCLUDE: cat Rpcb1.xsh | ++ ++Do not use this to run perl: C will run the perl that ++happens to be the first in your path and not necessarily the same perl that is ++used to run C. See L<"The INCLUDE_COMMAND: Keyword">. ++ ++=head2 The INCLUDE_COMMAND: Keyword ++ ++Runs the supplied command and includes its output into the current XS ++document. C assigns special meaning to the C<$^X> token ++in that it runs the same perl interpreter that is running C: ++ ++ INCLUDE_COMMAND: cat Rpcb1.xsh ++ ++ INCLUDE_COMMAND: $^X -e ... ++ ++=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 ALIAS: ++variable (see L<"The ALIAS: Keyword">), or maybe via the C variable ++(see L<"Variable-length Parameter Lists">). The last CASE: becomes the ++B case if it is not associated with a conditional. The following ++example shows CASE switched via C with a function C ++having an alias C. When the function is called as ++C its parameters are the usual C<(char *host, time_t *timep)>, ++but when the function is called as C 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 EXPORT_XSUB_SYMBOLS: Keyword ++ ++The EXPORT_XSUB_SYMBOLS: keyword is likely something you will never need. ++In perl versions earlier than 5.16.0, this keyword does nothing. Starting ++with 5.16, XSUB symbols are no longer exported by default. That is, they ++are C functions. If you include ++ ++ EXPORT_XSUB_SYMBOLS: ENABLE ++ ++in your XS code, the XSUBs following this line will not be declared C. ++You can later disable this with ++ ++ 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 C. ++ ++=head2 The & Unary Operator ++ ++The C<&> unary operator in the INPUT: section is used to tell B ++that it should convert a Perl value to/from C using the C type to the left ++of C<&>, 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 ++C or C but not an C or C). ++ ++The following XSUB will generate incorrect C code. The B compiler will ++turn this into code which calls C with parameters C<(char ++*host, time_t timep)>, but the real C wants the C ++parameter to be of type C rather than C. ++ ++ bool_t ++ rpcb_gettime(host,timep) ++ char *host ++ time_t timep ++ OUTPUT: ++ timep ++ ++That problem is corrected by using the C<&> operator. The B compiler ++will now turn this into code which calls C correctly with ++parameters C<(char *host, time_t *timep)>. It does this by carrying the ++C<&> through, so the function call looks like C. ++ ++ bool_t ++ rpcb_gettime(host,timep) ++ char *host ++ time_t &timep ++ OUTPUT: ++ timep ++ ++=head2 Inserting POD, Comments and C Preprocessor Directives ++ ++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 C<=cut> command; ++C 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 C<=>. 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 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 B 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 an XSUB name contains C<::>, 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 C, 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-Emethod() 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 C, 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 B then the C++ C function will be ++called and C 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 B then the C++ C 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, to be given as the first ++argument. ++ ++ color * ++ color::new() ++ ++The generated C++ code will call C. ++ ++ 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 (such as created by C) 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 C which converts negative values to C, or ++maybe croak()s. After this the return value of type C ++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 C<&> unary operator, ++and, possibly, using the NO_INIT keyword. ++Some others will require handling of types like C, 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 C.) ++ ++If the same C type is used in several different contexts which require ++different translations, C several new types mapped to this C type, ++and create separate F entries for these new types. Use these ++types in declarations of return type and parameters to XSUBs. ++ ++=head2 Perl Objects And C Structures ++ ++When dealing with C structures one should select either ++B or B 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. 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 will be created for C. The Perl ++object will be blessed in a class matching the name of the C ++type, with the tag C 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 ++L 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 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 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. ++ ++The easiest way to get a template set of macros to use is by specifying ++the C<-g> (C<--global>) option with h2xs (see L). ++ ++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; ++ ++=head3 MY_CXT REFERENCE ++ ++=over 5 ++ ++=item 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 ++ ++=item typedef my_cxt_t ++ ++This struct typedef I always be called C. The other ++C macros assume the existence of the C typedef name. ++ ++Declare a typedef named C that is a structure that contains ++all the data that needs to be interpreter-local. ++ ++ typedef struct { ++ int some_value; ++ } my_cxt_t; ++ ++=item START_MY_CXT ++ ++Always place the START_MY_CXT macro directly after the declaration ++of C. ++ ++=item MY_CXT_INIT ++ ++The MY_CXT_INIT macro initializes storage for the C struct. ++ ++It I 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 L below.) ++ ++=item dMY_CXT ++ ++Use the dMY_CXT macro (a declaration) in all the functions that access ++MY_CXT. ++ ++=item MY_CXT ++ ++Use the MY_CXT macro to access members of the C struct. For ++example, if C is ++ ++ typedef struct { ++ int index; ++ } my_cxt_t; ++ ++then use this to access the C member ++ ++ dMY_CXT; ++ MY_CXT.index = 2; ++ ++=item aMY_CXT/pMY_CXT ++ ++C 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/C macros, eg ++ ++ void sub1() { ++ dMY_CXT; ++ MY_CXT.index = 1; ++ sub2(aMY_CXT); ++ } ++ ++ void sub2(pMY_CXT) { ++ MY_CXT.index = 2; ++ } ++ ++Analogously to C, 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, C<_pMY_CXT> and C. ++ ++=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 (typically via the package's ++C 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 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 the Perl core, the wrapping ++does not take place before Perl 5.28. Starting in that release you can ++ ++ #define PERL_REENTRANT ++ ++in your code to enable the wrapping. It is advisable to do so if you ++are using such functions, as intermixing the C<_r>-forms (as Perl compiled ++for multithreaded operation will do) and the C<_r>-less forms is neither ++well-defined (inconsistent results, data corruption, or even crashes ++become more likely), nor is it very portable. Unfortunately, not all ++systems have all the C<_r> forms, but using this C<#define> gives you ++whatever protection that Perl is aware is available on each system. ++ ++=head1 EXAMPLES ++ ++File C: Interface to some ONC+ RPC bind library functions. ++ ++ #define PERL_NO_GET_CONTEXT ++ #include "EXTERN.h" ++ #include "perl.h" ++ #include "XSUB.h" ++ ++ #include ++ ++ 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: Custom typemap for RPC.xs. (cf. L) ++ ++ TYPEMAP ++ Netconfig * T_PTROBJ ++ ++File C: 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: 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 CAVEATS ++ ++XS code has full access to system calls including C library functions. ++It thus has the capability of interfering with things that the Perl core ++or other modules have set up, such as signal handlers or file handles. ++It could mess with the memory, or any number of harmful things. Don't. ++ ++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. XS code is viewed as a ++help-mate, to accomplish things that perl doesn't do, or doesn't do fast ++enough, but always subservient to perl. The closer XS code adheres to ++this model, the less likely conflicts will occur. ++ ++One area where there has been conflict is in regards to C locales. (See ++L.) 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 C> except for a couple of function calls in the ++POSIX module which of necessity use it. But the underlying locale, with ++that ++one exception is exposed to XS code, affecting all C library routines ++whose behavior is locale-dependent. Your XS code better not assume that ++the underlying locale is "C". The exception is the ++L|perllocale/Category LC_NUMERIC: Numeric Formatting> ++locale category, and the reason it is an exception is that experience ++has shown that it can be problematic for XS code, whereas we have not ++had reports of problems with the ++L. And the reason ++for this one category being problematic is that the character used as a ++decimal point can vary. Many European languages use a comma, whereas ++English, and hence Perl are expecting a dot (U+002E: FULL STOP). Many ++modules can handle only the radix character being a dot, and so perl ++attempts to make it so. Up through Perl v5.20, the attempt was merely ++to set C upon startup to the C<"C"> locale. Any ++L otherwise would change ++it; this caused some failures. Therefore, starting in v5.22, perl tries ++to keep C always set to C<"C"> for XS code. ++ ++To summarize, here's what to expect and how to handle locales in XS code: ++ ++=over ++ ++=item Non-locale-aware XS code ++ ++Keep in mind that even if you think your code is not locale-aware, it ++may call a 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 XS code except possibly C ++(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 L. ++ ++However, up through v5.20, Perl initialized things on start-up so that ++C 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 C 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 C in the "C" locale ++except around the operations internally where it should be something ++else. Misbehaving XS code will always be able to change the locale ++anyway, but the most common instance of this is checked for and ++handled. ++ ++=item Locale-aware XS code ++ ++If the locale from the user's environment is desired, there should be no ++need for XS code to set the locale except for C, as perl has ++already set the others up. XS code should avoid changing the locale, as ++it can adversely affect other, unrelated, code and may not be ++thread-safe. To minimize problems, the macros ++L, ++L, and ++L should be used to affect any needed ++change. ++ ++But, starting with Perl v5.28, locales are thread-safe on platforms that ++support this functionality. Windows has this starting with Visual ++Studio 2005. Many other modern platforms support the thread-safe POSIX ++2008 functions. The C C<#define> C will be ++defined iff this build is using these. From Perl-space, the read-only ++variable C<${SAFE_LOCALES}> is 1 if either the build is not threaded, or ++if C is defined; otherwise it is 0. ++ ++The way this works under-the-hood is that every thread has a choice of ++using a locale specific to it (this is the Windows and POSIX 2008 ++functionality), or the global locale that is accessible to all threads ++(this is the functionality that has always been there). The ++implementations for Windows and POSIX are completely different. On ++Windows, the runtime can be set up so that the standard ++L> function either only knows about the global locale or ++the locale for this thread. On POSIX, C always deals with ++the global locale, and other functions have been created to handle ++per-thread locales. Perl makes this transparent to perl-space code. It ++continues to use C, and the interpreter translates ++that into the per-thread functions. ++ ++All other locale-senstive functions automatically use the per-thread ++locale, if that is turned on, and failing that, the global locale. Thus ++calls to C are ineffective on POSIX systems for the current ++thread if that thread is using a per-thread locale. If perl is compiled ++for single-thread operation, it does not use the per-thread functions, ++so C does work as expected. ++ ++If you have loaded the L> module you can use the methods given ++in L to call L|POSIX/setlocale> to safely ++change or query the locale (on systems where it is safe to do so), or ++you can use the new 5.28 function L instead, ++which is a drop-in replacement for the system L>, and ++handles single-threaded and multi-threaded applications transparently. ++ ++There are some locale-related library calls that still aren't ++thread-safe because they return data in a buffer global to all threads. ++In the past, these didn't matter as locales weren't thread-safe at all. ++But now you have to be aware of them in case your module is called in a ++multi-threaded application. The known ones are ++ ++ asctime() ++ ctime() ++ gcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)] ++ getdate() ++ wcrtomb() if its final argument is NULL ++ wcsrtombs() if its final argument is NULL ++ wcstombs() ++ wctomb() ++ ++Some of these shouldn't really be called in a Perl application, and for ++others there are thread-safe versions of these already implemented: ++ ++ asctime_r() ++ ctime_r() ++ Perl_langinfo() ++ ++The C<_r> forms are automatically used, starting in Perl 5.28, if you ++compile your code, with ++ ++ #define PERL_REENTRANT ++ ++See also L. ++You can use the methods given in L, to get the best available ++locale-safe versions of these ++ ++ POSIX::localeconv() ++ POSIX::wcstombs() ++ POSIX::wctomb() ++ ++And note, that some items returned by C are available ++through L. ++ ++The others shouldn't be used in a threaded application. ++ ++Some modules may call a non-perl library that is locale-aware. This is ++fine as long as it doesn't try to query or change the locale using the ++system C. But if these do call the system C, ++those calls may be ineffective. Instead, ++L|perlapi/Perl_setlocale> works in all circumstances. ++Plain setlocale is ineffective on multi-threaded POSIX 2008 systems. It ++operates only on the global locale, whereas each thread has its own ++locale, paying no attention to the global one. Since converting ++these non-Perl libraries to C is out of the question, ++there is a new function in v5.28 ++L|perlapi/switch_to_global_locale> that will ++switch the thread it is called from so that any system C ++calls will have their desired effect. The function ++L|perlapi/sync_locale> must be called before returning to ++perl. ++ ++This thread can change the locale all it wants and it won't affect any ++other thread, except any that also have been switched to the global ++locale. This means that a multi-threaded application can have a single ++thread using an alien library without a problem; but no more than a ++single thread can be so-occupied. Bad results likely will happen. ++ ++In perls without multi-thread locale support, some alien libraries, ++such as C change locales. This can cause problems for the Perl ++core and other modules. For these, before control is returned to ++perl, starting in v5.20.1, calling the function ++L from XS should 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)); ++ ++or use the methods given in L. ++ ++=back ++ ++=head1 XS VERSION ++ ++This document covers features supported by C ++(also known as C) 3.13_01. ++ ++=head1 AUTHOR ++ ++Originally written by Dean Roehrich >. ++ ++Maintained since 1996 by The Perl Porters >. +diff --git a/lib/perlxstut.pod b/lib/perlxstut.pod +new file mode 100644 +index 0000000..ef154ad +--- /dev/null ++++ b/lib/perlxstut.pod +@@ -0,0 +1,1401 @@ ++=head1 NAME ++ ++perlxstut - Tutorial for writing XSUBs ++ ++=head1 DESCRIPTION ++ ++This tutorial will educate the reader on the steps involved in creating ++a Perl extension. The reader is assumed to have access to L, ++L and L. ++ ++This tutorial starts with very simple examples and becomes more complex, ++with each new example adding new features. Certain concepts may not be ++completely explained until later in the tutorial in order to slowly ease ++the reader into building extensions. ++ ++This tutorial was written from a Unix point of view. Where I know them ++to be otherwise different for other platforms (e.g. Win32), I will list ++them. If you find something that was missed, please let me know. ++ ++=head1 SPECIAL NOTES ++ ++=head2 make ++ ++This tutorial assumes that the make program that Perl is configured to ++use is called C. Instead of running "make" in the examples that ++follow, you may have to substitute whatever make program Perl has been ++configured to use. Running B should tell you what it is. ++ ++=head2 Version caveat ++ ++When writing a Perl extension for general consumption, one should expect that ++the extension will be used with versions of Perl different from the ++version available on your machine. Since you are reading this document, ++the version of Perl on your machine is probably 5.005 or later, but the users ++of your extension may have more ancient versions. ++ ++To understand what kinds of incompatibilities one may expect, and in the rare ++case that the version of Perl on your machine is older than this document, ++see the section on "Troubleshooting these Examples" for more information. ++ ++If your extension uses some features of Perl which are not available on older ++releases of Perl, your users would appreciate an early meaningful warning. ++You would probably put this information into the F file, but nowadays ++installation of extensions may be performed automatically, guided by F ++module or other tools. ++ ++In MakeMaker-based installations, F provides the earliest ++opportunity to perform version checks. One can put something like this ++in F for this purpose: ++ ++ eval { require 5.007 } ++ or die < build them, but you must link the XSUBs subroutines with the ++rest of Perl, creating a new executable. This situation is similar to ++Perl 4. ++ ++This tutorial can still be used on such a system. The XSUB build mechanism ++will check the system and build a dynamically-loadable library if possible, ++or else a static library and then, optionally, a new statically-linked ++executable with that static library linked in. ++ ++Should you wish to build a statically-linked executable on a system which ++can dynamically load libraries, you may, in all the following examples, ++where the command "C" with no arguments is executed, run the command ++"C" instead. ++ ++If you have generated such a statically-linked executable by choice, then ++instead of saying "C", you should say "C". ++On systems that cannot build dynamically-loadable libraries at all, simply ++saying "C" is sufficient. ++ ++=head2 Threads and PERL_NO_GET_CONTEXT ++ ++For threaded builds, perl requires the context pointer for the current ++thread, without C, perl will call a function to ++retrieve the context. ++ ++For improved performance, include: ++ ++ #define PERL_NO_GET_CONTEXT ++ ++as shown below. ++ ++For more details, see L. ++ ++=head1 TUTORIAL ++ ++Now let's go on with the show! ++ ++=head2 EXAMPLE 1 ++ ++Our first extension will be very simple. When we call the routine in the ++extension, it will print out a well-known message and return. ++ ++Run "C". This creates a directory named Mytest, ++possibly under ext/ if that directory exists in the current working ++directory. Several files will be created under the Mytest dir, including ++MANIFEST, Makefile.PL, lib/Mytest.pm, Mytest.xs, t/Mytest.t, and Changes. ++ ++The MANIFEST file contains the names of all the files just created in the ++Mytest directory. ++ ++The file Makefile.PL should look something like this: ++ ++ use ExtUtils::MakeMaker; ++ # See lib/ExtUtils/MakeMaker.pm for details of how to influence ++ # the contents of the Makefile that is written. ++ WriteMakefile( ++ NAME => 'Mytest', ++ VERSION_FROM => 'Mytest.pm', # finds $VERSION ++ LIBS => [''], # e.g., '-lm' ++ DEFINE => '', # e.g., '-DHAVE_SOMETHING' ++ INC => '', # e.g., '-I/usr/include/other' ++ ); ++ ++The file Mytest.pm should start with something like this: ++ ++ package Mytest; ++ ++ use 5.008008; ++ use strict; ++ use warnings; ++ ++ require Exporter; ++ ++ our @ISA = qw(Exporter); ++ our %EXPORT_TAGS = ( 'all' => [ qw( ++ ++ ) ] ); ++ ++ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); ++ ++ our @EXPORT = qw( ++ ++ ); ++ ++ our $VERSION = '0.01'; ++ ++ require XSLoader; ++ XSLoader::load('Mytest', $VERSION); ++ ++ # Preloaded methods go here. ++ ++ 1; ++ __END__ ++ # Below is the stub of documentation for your module. You better ++ # edit it! ++ ++The rest of the .pm file contains sample code for providing documentation for ++the extension. ++ ++Finally, the Mytest.xs file should look something like this: ++ ++ #define PERL_NO_GET_CONTEXT ++ #include "EXTERN.h" ++ #include "perl.h" ++ #include "XSUB.h" ++ ++ #include "ppport.h" ++ ++ MODULE = Mytest PACKAGE = Mytest ++ ++Let's edit the .xs file by adding this to the end of the file: ++ ++ void ++ hello() ++ CODE: ++ printf("Hello, world!\n"); ++ ++It is okay for the lines starting at the "CODE:" line to not be indented. ++However, for readability purposes, it is suggested that you indent CODE: ++one level and the lines following one more level. ++ ++Now we'll run "C". This will create a real Makefile, ++which make needs. Its output looks something like: ++ ++ % perl Makefile.PL ++ Checking if your kit is complete... ++ Looks good ++ Writing Makefile for Mytest ++ % ++ ++Now, running make will produce output that looks something like this (some ++long lines have been shortened for clarity and some extraneous lines have ++been deleted): ++ ++ % make ++ cp lib/Mytest.pm blib/lib/Mytest.pm ++ perl xsubpp -typemap typemap Mytest.xs > Mytest.xsc && \ ++ mv Mytest.xsc Mytest.c ++ Please specify prototyping behavior for Mytest.xs (see perlxs manual) ++ cc -c Mytest.c ++ Running Mkbootstrap for Mytest () ++ chmod 644 Mytest.bs ++ rm -f blib/arch/auto/Mytest/Mytest.so ++ cc -shared -L/usr/local/lib Mytest.o -o blib/arch/auto/Mytest/Mytest.so ++ ++ chmod 755 blib/arch/auto/Mytest/Mytest.so ++ cp Mytest.bs blib/arch/auto/Mytest/Mytest.bs ++ chmod 644 blib/arch/auto/Mytest/Mytest.bs ++ Manifying blib/man3/Mytest.3pm ++ % ++ ++You can safely ignore the line about "prototyping behavior" - it is ++explained in L. ++ ++Perl has its own special way of easily writing test scripts, but for this ++example only, we'll create our own test script. Create a file called hello ++that looks like this: ++ ++ #! /opt/perl5/bin/perl ++ ++ use ExtUtils::testlib; ++ ++ use Mytest; ++ ++ Mytest::hello(); ++ ++Now we make the script executable (C), run the script ++and we should see the following output: ++ ++ % ./hello ++ Hello, world! ++ % ++ ++=head2 EXAMPLE 2 ++ ++Now let's add to our extension a subroutine that will take a single numeric ++argument as input and return 1 if the number is even or 0 if the number ++is odd. ++ ++Add the following to the end of Mytest.xs: ++ ++ int ++ is_even(input) ++ int input ++ CODE: ++ RETVAL = (input % 2 == 0); ++ OUTPUT: ++ RETVAL ++ ++There does not need to be whitespace at the start of the "C" ++line, but it is useful for improving readability. Placing a semi-colon at ++the end of that line is also optional. Any amount and kind of whitespace ++may be placed between the "C" and "C". ++ ++Now re-run make to rebuild our new shared library. ++ ++Now perform the same steps as before, generating a Makefile from the ++Makefile.PL file, and running make. ++ ++In order to test that our extension works, we now need to look at the ++file Mytest.t. This file is set up to imitate the same kind of testing ++structure that Perl itself has. Within the test script, you perform a ++number of tests to confirm the behavior of the extension, printing "ok" ++when the test is correct, "not ok" when it is not. ++ ++ use Test::More tests => 4; ++ BEGIN { use_ok('Mytest') }; ++ ++ ######################### ++ ++ # Insert your test code below, the Test::More module is use()ed here ++ # so read its man page ( perldoc Test::More ) for help writing this ++ # test script. ++ ++ is(&Mytest::is_even(0), 1); ++ is(&Mytest::is_even(1), 0); ++ is(&Mytest::is_even(2), 1); ++ ++We will be calling the test script through the command "C". You ++should see output that looks something like this: ++ ++ %make test ++ PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" ++ "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t ++ t/Mytest....ok ++ All tests successful. ++ Files=1, Tests=4, 0 wallclock secs ( 0.03 cusr + 0.00 csys = 0.03 CPU) ++ % ++ ++=head2 What has gone on? ++ ++The program h2xs is the starting point for creating extensions. In later ++examples we'll see how we can use h2xs to read header files and generate ++templates to connect to C routines. ++ ++h2xs creates a number of files in the extension directory. The file ++Makefile.PL is a perl script which will generate a true Makefile to build ++the extension. We'll take a closer look at it later. ++ ++The .pm and .xs files contain the meat of the extension. The .xs file holds ++the C routines that make up the extension. The .pm file contains routines ++that tell Perl how to load your extension. ++ ++Generating the Makefile and running C created a directory called blib ++(which stands for "build library") in the current working directory. This ++directory will contain the shared library that we will build. Once we have ++tested it, we can install it into its final location. ++ ++Invoking the test script via "C" did something very important. ++It invoked perl with all those C<-I> arguments so that it could find the ++various files that are part of the extension. It is I important that ++while you are still testing extensions that you use "C". If you ++try to run the test script all by itself, you will get a fatal error. ++Another reason it is important to use "C" to run your test ++script is that if you are testing an upgrade to an already-existing version, ++using "C" ensures that you will test your new extension, not the ++already-existing version. ++ ++When Perl sees a C, it searches for a file with the same name ++as the C'd extension that has a .pm suffix. If that file cannot be found, ++Perl dies with a fatal error. The default search path is contained in the ++C<@INC> array. ++ ++In our case, Mytest.pm tells perl that it will need the Exporter and Dynamic ++Loader extensions. It then sets the C<@ISA> and C<@EXPORT> arrays and the ++C<$VERSION> scalar; finally it tells perl to bootstrap the module. Perl ++will call its dynamic loader routine (if there is one) and load the shared ++library. ++ ++The two arrays C<@ISA> and C<@EXPORT> are very important. The C<@ISA> ++array contains a list of other packages in which to search for methods (or ++subroutines) that do not exist in the current package. This is usually ++only important for object-oriented extensions (which we will talk about ++much later), and so usually doesn't need to be modified. ++ ++The C<@EXPORT> array tells Perl which of the extension's variables and ++subroutines should be placed into the calling package's namespace. Because ++you don't know if the user has already used your variable and subroutine ++names, it's vitally important to carefully select what to export. Do I ++export method or variable names I without a good reason. ++ ++As a general rule, if the module is trying to be object-oriented then don't ++export anything. If it's just a collection of functions and variables, then ++you can export them via another array, called C<@EXPORT_OK>. This array ++does not automatically place its subroutine and variable names into the ++namespace unless the user specifically requests that this be done. ++ ++See L for more information. ++ ++The C<$VERSION> variable is used to ensure that the .pm file and the shared ++library are "in sync" with each other. Any time you make changes to ++the .pm or .xs files, you should increment the value of this variable. ++ ++=head2 Writing good test scripts ++ ++The importance of writing good test scripts cannot be over-emphasized. You ++should closely follow the "ok/not ok" style that Perl itself uses, so that ++it is very easy and unambiguous to determine the outcome of each test case. ++When you find and fix a bug, make sure you add a test case for it. ++ ++By running "C", you ensure that your Mytest.t script runs and uses ++the correct version of your extension. If you have many test cases, ++save your test files in the "t" directory and use the suffix ".t". ++When you run "C", all of these test files will be executed. ++ ++=head2 EXAMPLE 3 ++ ++Our third extension will take one argument as its input, round off that ++value, and set the I to the rounded value. ++ ++Add the following to the end of Mytest.xs: ++ ++ void ++ round(arg) ++ double arg ++ CODE: ++ if (arg > 0.0) { ++ arg = floor(arg + 0.5); ++ } else if (arg < 0.0) { ++ arg = ceil(arg - 0.5); ++ } else { ++ arg = 0.0; ++ } ++ OUTPUT: ++ arg ++ ++Edit the Makefile.PL file so that the corresponding line looks like this: ++ ++ 'LIBS' => ['-lm'], # e.g., '-lm' ++ ++Generate the Makefile and run make. Change the test number in Mytest.t to ++"9" and add the following tests: ++ ++ $i = -1.5; &Mytest::round($i); is( $i, -2.0 ); ++ $i = -1.1; &Mytest::round($i); is( $i, -1.0 ); ++ $i = 0.0; &Mytest::round($i); is( $i, 0.0 ); ++ $i = 0.5; &Mytest::round($i); is( $i, 1.0 ); ++ $i = 1.2; &Mytest::round($i); is( $i, 1.0 ); ++ ++Running "C" should now print out that all nine tests are okay. ++ ++Notice that in these new test cases, the argument passed to round was a ++scalar variable. You might be wondering if you can round a constant or ++literal. To see what happens, temporarily add the following line to Mytest.t: ++ ++ &Mytest::round(3); ++ ++Run "C" and notice that Perl dies with a fatal error. Perl won't ++let you change the value of constants! ++ ++=head2 What's new here? ++ ++=over 4 ++ ++=item * ++ ++We've made some changes to Makefile.PL. In this case, we've specified an ++extra library to be linked into the extension's shared library, the math ++library libm in this case. We'll talk later about how to write XSUBs that ++can call every routine in a library. ++ ++=item * ++ ++The value of the function is not being passed back as the function's return ++value, but by changing the value of the variable that was passed into the ++function. You might have guessed that when you saw that the return value ++of round is of type "void". ++ ++=back ++ ++=head2 Input and Output Parameters ++ ++You specify the parameters that will be passed into the XSUB on the line(s) ++after you declare the function's return value and name. Each input parameter ++line starts with optional whitespace, and may have an optional terminating ++semicolon. ++ ++The list of output parameters occurs at the very end of the function, just ++after the OUTPUT: directive. The use of RETVAL tells Perl that you ++wish to send this value back as the return value of the XSUB function. In ++Example 3, we wanted the "return value" placed in the original variable ++which we passed in, so we listed it (and not RETVAL) in the OUTPUT: section. ++ ++=head2 The XSUBPP Program ++ ++The B program takes the XS code in the .xs file and translates it into ++C code, placing it in a file whose suffix is .c. The C code created makes ++heavy use of the C functions within Perl. ++ ++=head2 The TYPEMAP file ++ ++The B program uses rules to convert from Perl's data types (scalar, ++array, etc.) to C's data types (int, char, etc.). These rules are stored ++in the typemap file ($PERLLIB/ExtUtils/typemap). There's a brief discussion ++below, but all the nitty-gritty details can be found in L. ++If you have a new-enough version of perl (5.16 and up) or an upgraded ++XS compiler (C 3.13_01 or better), then you can inline ++typemaps in your XS instead of writing separate files. ++Either way, this typemap thing is split into three parts: ++ ++The first section maps various C data types to a name, which corresponds ++somewhat with the various Perl types. The second section contains C code ++which B uses to handle input parameters. The third section contains ++C code which B uses to handle output parameters. ++ ++Let's take a look at a portion of the .c file created for our extension. ++The file name is Mytest.c: ++ ++ XS(XS_Mytest_round) ++ { ++ dXSARGS; ++ if (items != 1) ++ Perl_croak(aTHX_ "Usage: Mytest::round(arg)"); ++ PERL_UNUSED_VAR(cv); /* -W */ ++ { ++ double arg = (double)SvNV(ST(0)); /* XXXXX */ ++ if (arg > 0.0) { ++ arg = floor(arg + 0.5); ++ } else if (arg < 0.0) { ++ arg = ceil(arg - 0.5); ++ } else { ++ arg = 0.0; ++ } ++ sv_setnv(ST(0), (double)arg); /* XXXXX */ ++ SvSETMAGIC(ST(0)); ++ } ++ XSRETURN_EMPTY; ++ } ++ ++Notice the two lines commented with "XXXXX". If you check the first part ++of the typemap file (or section), you'll see that doubles are of type ++T_DOUBLE. In the INPUT part of the typemap, an argument that is T_DOUBLE ++is assigned to the variable arg by calling the routine SvNV on something, ++then casting it to double, then assigned to the variable arg. Similarly, ++in the OUTPUT section, once arg has its final value, it is passed to the ++sv_setnv function to be passed back to the calling subroutine. These two ++functions are explained in L; we'll talk more later about what ++that "ST(0)" means in the section on the argument stack. ++ ++=head2 Warning about Output Arguments ++ ++In general, it's not a good idea to write extensions that modify their input ++parameters, as in Example 3. Instead, you should probably return multiple ++values in an array and let the caller handle them (we'll do this in a later ++example). However, in order to better accommodate calling pre-existing C ++routines, which often do modify their input parameters, this behavior is ++tolerated. ++ ++=head2 EXAMPLE 4 ++ ++In this example, we'll now begin to write XSUBs that will interact with ++pre-defined C libraries. To begin with, we will build a small library of ++our own, then let h2xs write our .pm and .xs files for us. ++ ++Create a new directory called Mytest2 at the same level as the directory ++Mytest. In the Mytest2 directory, create another directory called mylib, ++and cd into that directory. ++ ++Here we'll create some files that will generate a test library. These will ++include a C source file and a header file. We'll also create a Makefile.PL ++in this directory. Then we'll make sure that running make at the Mytest2 ++level will automatically run this Makefile.PL file and the resulting Makefile. ++ ++In the mylib directory, create a file mylib.h that looks like this: ++ ++ #define TESTVAL 4 ++ ++ extern double foo(int, long, const char*); ++ ++Also create a file mylib.c that looks like this: ++ ++ #include ++ #include "./mylib.h" ++ ++ double ++ foo(int a, long b, const char *c) ++ { ++ return (a + b + atof(c) + TESTVAL); ++ } ++ ++And finally create a file Makefile.PL that looks like this: ++ ++ use ExtUtils::MakeMaker; ++ $Verbose = 1; ++ WriteMakefile( ++ NAME => 'Mytest2::mylib', ++ SKIP => [qw(all static static_lib dynamic dynamic_lib)], ++ clean => {'FILES' => 'libmylib$(LIB_EXT)'}, ++ ); ++ ++ ++ sub MY::top_targets { ++ ' ++ all :: static ++ ++ pure_all :: static ++ ++ static :: libmylib$(LIB_EXT) ++ ++ libmylib$(LIB_EXT): $(O_FILES) ++ $(AR) cr libmylib$(LIB_EXT) $(O_FILES) ++ $(RANLIB) libmylib$(LIB_EXT) ++ ++ '; ++ } ++ ++Make sure you use a tab and not spaces on the lines beginning with "$(AR)" ++and "$(RANLIB)". Make will not function properly if you use spaces. ++It has also been reported that the "cr" argument to $(AR) is unnecessary ++on Win32 systems. ++ ++We will now create the main top-level Mytest2 files. Change to the directory ++above Mytest2 and run the following command: ++ ++ % h2xs -O -n Mytest2 ./Mytest2/mylib/mylib.h ++ ++This will print out a warning about overwriting Mytest2, but that's okay. ++Our files are stored in Mytest2/mylib, and will be untouched. ++ ++The normal Makefile.PL that h2xs generates doesn't know about the mylib ++directory. We need to tell it that there is a subdirectory and that we ++will be generating a library in it. Let's add the argument MYEXTLIB to ++the WriteMakefile call so that it looks like this: ++ ++ WriteMakefile( ++ 'NAME' => 'Mytest2', ++ 'VERSION_FROM' => 'Mytest2.pm', # finds $VERSION ++ 'LIBS' => [''], # e.g., '-lm' ++ 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' ++ 'INC' => '', # e.g., '-I/usr/include/other' ++ 'MYEXTLIB' => 'mylib/libmylib$(LIB_EXT)', ++ ); ++ ++and then at the end add a subroutine (which will override the pre-existing ++subroutine). Remember to use a tab character to indent the line beginning ++with "cd"! ++ ++ sub MY::postamble { ++ ' ++ $(MYEXTLIB): mylib/Makefile ++ cd mylib && $(MAKE) $(PASSTHRU) ++ '; ++ } ++ ++Let's also fix the MANIFEST file so that it accurately reflects the contents ++of our extension. The single line that says "mylib" should be replaced by ++the following three lines: ++ ++ mylib/Makefile.PL ++ mylib/mylib.c ++ mylib/mylib.h ++ ++To keep our namespace nice and unpolluted, edit the .pm file and change ++the variable C<@EXPORT> to C<@EXPORT_OK>. Finally, in the ++.xs file, edit the #include line to read: ++ ++ #include "mylib/mylib.h" ++ ++And also add the following function definition to the end of the .xs file: ++ ++ double ++ foo(a,b,c) ++ int a ++ long b ++ const char * c ++ OUTPUT: ++ RETVAL ++ ++Now we also need to create a typemap because the default Perl doesn't ++currently support the C type. Include a new TYPEMAP ++section in your XS code before the above function: ++ ++ TYPEMAP: <" and all should be well. There are some warnings on missing ++tests for the Mytest2::mylib extension, but you can ignore them. ++ ++=head2 What has happened here? ++ ++Unlike previous examples, we've now run h2xs on a real include file. This ++has caused some extra goodies to appear in both the .pm and .xs files. ++ ++=over 4 ++ ++=item * ++ ++In the .xs file, there's now a #include directive with the absolute path to ++the mylib.h header file. We changed this to a relative path so that we ++could move the extension directory if we wanted to. ++ ++=item * ++ ++There's now some new C code that's been added to the .xs file. The purpose ++of the C routine is to make the values that are #define'd in the ++header file accessible by the Perl script (by calling either C or ++C<&Mytest2::TESTVAL>). There's also some XS code to allow calls to the ++C routine. ++ ++=item * ++ ++The .pm file originally exported the name C in the C<@EXPORT> array. ++This could lead to name clashes. A good rule of thumb is that if the #define ++is only going to be used by the C routines themselves, and not by the user, ++they should be removed from the C<@EXPORT> array. Alternately, if you don't ++mind using the "fully qualified name" of a variable, you could move most ++or all of the items from the C<@EXPORT> array into the C<@EXPORT_OK> array. ++ ++=item * ++ ++If our include file had contained #include directives, these would not have ++been processed by h2xs. There is no good solution to this right now. ++ ++=item * ++ ++We've also told Perl about the library that we built in the mylib ++subdirectory. That required only the addition of the C variable ++to the WriteMakefile call and the replacement of the postamble subroutine ++to cd into the subdirectory and run make. The Makefile.PL for the ++library is a bit more complicated, but not excessively so. Again we ++replaced the postamble subroutine to insert our own code. This code ++simply specified that the library to be created here was a static archive ++library (as opposed to a dynamically loadable library) and provided the ++commands to build it. ++ ++=back ++ ++=head2 Anatomy of .xs file ++ ++The .xs file of L<"EXAMPLE 4"> contained some new elements. To understand ++the meaning of these elements, pay attention to the line which reads ++ ++ MODULE = Mytest2 PACKAGE = Mytest2 ++ ++Anything before this line is plain C code which describes which headers ++to include, and defines some convenience functions. No translations are ++performed on this part, apart from having embedded POD documentation ++skipped over (see L) it goes into the generated output C file as is. ++ ++Anything after this line is the description of XSUB functions. ++These descriptions are translated by B into C code which ++implements these functions using Perl calling conventions, and which ++makes these functions visible from Perl interpreter. ++ ++Pay a special attention to the function C. This name appears ++twice in the generated .xs file: once in the first part, as a static C ++function, then another time in the second part, when an XSUB interface to ++this static C function is defined. ++ ++This is quite typical for .xs files: usually the .xs file provides ++an interface to an existing C function. Then this C function is defined ++somewhere (either in an external library, or in the first part of .xs file), ++and a Perl interface to this function (i.e. "Perl glue") is described in the ++second part of .xs file. The situation in L<"EXAMPLE 1">, L<"EXAMPLE 2">, ++and L<"EXAMPLE 3">, when all the work is done inside the "Perl glue", is ++somewhat of an exception rather than the rule. ++ ++=head2 Getting the fat out of XSUBs ++ ++In L<"EXAMPLE 4"> the second part of .xs file contained the following ++description of an XSUB: ++ ++ double ++ foo(a,b,c) ++ int a ++ long b ++ const char * c ++ OUTPUT: ++ RETVAL ++ ++Note that in contrast with L<"EXAMPLE 1">, L<"EXAMPLE 2"> and L<"EXAMPLE 3">, ++this description does not contain the actual I for what is done ++during a call to Perl function foo(). To understand what is going ++on here, one can add a CODE section to this XSUB: ++ ++ double ++ foo(a,b,c) ++ int a ++ long b ++ const char * c ++ CODE: ++ RETVAL = foo(a,b,c); ++ OUTPUT: ++ RETVAL ++ ++However, these two XSUBs provide almost identical generated C code: B ++compiler is smart enough to figure out the C section from the first ++two lines of the description of XSUB. What about C section? In ++fact, that is absolutely the same! The C section can be removed ++as well, I section or C section> is not ++specified: B can see that it needs to generate a function call ++section, and will autogenerate the OUTPUT section too. Thus one can ++shortcut the XSUB to become: ++ ++ double ++ foo(a,b,c) ++ int a ++ long b ++ const char * c ++ ++Can we do the same with an XSUB ++ ++ int ++ is_even(input) ++ int input ++ CODE: ++ RETVAL = (input % 2 == 0); ++ OUTPUT: ++ RETVAL ++ ++of L<"EXAMPLE 2">? To do this, one needs to define a C function C. As we saw in L, a proper place ++for this definition is in the first part of .xs file. In fact a C function ++ ++ int ++ is_even(int arg) ++ { ++ return (arg % 2 == 0); ++ } ++ ++is probably overkill for this. Something as simple as a C<#define> will ++do too: ++ ++ #define is_even(arg) ((arg) % 2 == 0) ++ ++After having this in the first part of .xs file, the "Perl glue" part becomes ++as simple as ++ ++ int ++ is_even(input) ++ int input ++ ++This technique of separation of the glue part from the workhorse part has ++obvious tradeoffs: if you want to change a Perl interface, you need to ++change two places in your code. However, it removes a lot of clutter, ++and makes the workhorse part independent from idiosyncrasies of Perl calling ++convention. (In fact, there is nothing Perl-specific in the above description, ++a different version of B might have translated this to TCL glue or ++Python glue as well.) ++ ++=head2 More about XSUB arguments ++ ++With the completion of Example 4, we now have an easy way to simulate some ++real-life libraries whose interfaces may not be the cleanest in the world. ++We shall now continue with a discussion of the arguments passed to the ++B compiler. ++ ++When you specify arguments to routines in the .xs file, you are really ++passing three pieces of information for each argument listed. The first ++piece is the order of that argument relative to the others (first, second, ++etc). The second is the type of argument, and consists of the type ++declaration of the argument (e.g., int, char*, etc). The third piece is ++the calling convention for the argument in the call to the library function. ++ ++While Perl passes arguments to functions by reference, ++C passes arguments by value; to implement a C function which modifies data ++of one of the "arguments", the actual argument of this C function would be ++a pointer to the data. Thus two C functions with declarations ++ ++ int string_length(char *s); ++ int upper_case_char(char *cp); ++ ++may have completely different semantics: the first one may inspect an array ++of chars pointed by s, and the second one may immediately dereference C ++and manipulate C<*cp> only (using the return value as, say, a success ++indicator). From Perl one would use these functions in ++a completely different manner. ++ ++One conveys this info to B by replacing C<*> before the ++argument by C<&>. C<&> means that the argument should be passed to a library ++function by its address. The above two function may be XSUB-ified as ++ ++ int ++ string_length(s) ++ char * s ++ ++ int ++ upper_case_char(cp) ++ char &cp ++ ++For example, consider: ++ ++ int ++ foo(a,b) ++ char &a ++ char * b ++ ++The first Perl argument to this function would be treated as a char and ++assigned to the variable a, and its address would be passed into the function ++foo. The second Perl argument would be treated as a string pointer and assigned ++to the variable b. The I of b would be passed into the function foo. ++The actual call to the function foo that B generates would look like ++this: ++ ++ foo(&a, b); ++ ++B will parse the following function argument lists identically: ++ ++ char &a ++ char&a ++ char & a ++ ++However, to help ease understanding, it is suggested that you place a "&" ++next to the variable name and away from the variable type), and place a ++"*" near the variable type, but away from the variable name (as in the ++call to foo above). By doing so, it is easy to understand exactly what ++will be passed to the C function; it will be whatever is in the "last ++column". ++ ++You should take great pains to try to pass the function the type of variable ++it wants, when possible. It will save you a lot of trouble in the long run. ++ ++=head2 The Argument Stack ++ ++If we look at any of the C code generated by any of the examples except ++example 1, you will notice a number of references to ST(n), where n is ++usually 0. "ST" is actually a macro that points to the n'th argument ++on the argument stack. ST(0) is thus the first argument on the stack and ++therefore the first argument passed to the XSUB, ST(1) is the second ++argument, and so on. ++ ++When you list the arguments to the XSUB in the .xs file, that tells B ++which argument corresponds to which of the argument stack (i.e., the first ++one listed is the first argument, and so on). You invite disaster if you ++do not list them in the same order as the function expects them. ++ ++The actual values on the argument stack are pointers to the values passed ++in. When an argument is listed as being an OUTPUT value, its corresponding ++value on the stack (i.e., ST(0) if it was the first argument) is changed. ++You can verify this by looking at the C code generated for Example 3. ++The code for the round() XSUB routine contains lines that look like this: ++ ++ double arg = (double)SvNV(ST(0)); ++ /* Round the contents of the variable arg */ ++ sv_setnv(ST(0), (double)arg); ++ ++The arg variable is initially set by taking the value from ST(0), then is ++stored back into ST(0) at the end of the routine. ++ ++XSUBs are also allowed to return lists, not just scalars. This must be ++done by manipulating stack values ST(0), ST(1), etc, in a subtly ++different way. See L for details. ++ ++XSUBs are also allowed to avoid automatic conversion of Perl function arguments ++to C function arguments. See L for details. Some people prefer ++manual conversion by inspecting C even in the cases when automatic ++conversion will do, arguing that this makes the logic of an XSUB call clearer. ++Compare with L<"Getting the fat out of XSUBs"> for a similar tradeoff of ++a complete separation of "Perl glue" and "workhorse" parts of an XSUB. ++ ++While experts may argue about these idioms, a novice to Perl guts may ++prefer a way which is as little Perl-guts-specific as possible, meaning ++automatic conversion and automatic call generation, as in ++L<"Getting the fat out of XSUBs">. This approach has the additional ++benefit of protecting the XSUB writer from future changes to the Perl API. ++ ++=head2 Extending your Extension ++ ++Sometimes you might want to provide some extra methods or subroutines ++to assist in making the interface between Perl and your extension simpler ++or easier to understand. These routines should live in the .pm file. ++Whether they are automatically loaded when the extension itself is loaded ++or only loaded when called depends on where in the .pm file the subroutine ++definition is placed. You can also consult L for an alternate ++way to store and load your extra subroutines. ++ ++=head2 Documenting your Extension ++ ++There is absolutely no excuse for not documenting your extension. ++Documentation belongs in the .pm file. This file will be fed to pod2man, ++and the embedded documentation will be converted to the manpage format, ++then placed in the blib directory. It will be copied to Perl's ++manpage directory when the extension is installed. ++ ++You may intersperse documentation and Perl code within the .pm file. ++In fact, if you want to use method autoloading, you must do this, ++as the comment inside the .pm file explains. ++ ++See L for more information about the pod format. ++ ++=head2 Installing your Extension ++ ++Once your extension is complete and passes all its tests, installing it ++is quite simple: you simply run "make install". You will either need ++to have write permission into the directories where Perl is installed, ++or ask your system administrator to run the make for you. ++ ++Alternately, you can specify the exact directory to place the extension's ++files by placing a "PREFIX=/destination/directory" after the make install ++(or in between the make and install if you have a brain-dead version of make). ++This can be very useful if you are building an extension that will eventually ++be distributed to multiple systems. You can then just archive the files in ++the destination directory and distribute them to your destination systems. ++ ++=head2 EXAMPLE 5 ++ ++In this example, we'll do some more work with the argument stack. The ++previous examples have all returned only a single value. We'll now ++create an extension that returns an array. ++ ++This extension is very Unix-oriented (struct statfs and the statfs system ++call). If you are not running on a Unix system, you can substitute for ++statfs any other function that returns multiple values, you can hard-code ++values to be returned to the caller (although this will be a bit harder ++to test the error case), or you can simply not do this example. If you ++change the XSUB, be sure to fix the test cases to match the changes. ++ ++Return to the Mytest directory and add the following code to the end of ++Mytest.xs: ++ ++ void ++ statfs(path) ++ char * path ++ INIT: ++ int i; ++ struct statfs buf; ++ ++ PPCODE: ++ i = statfs(path, &buf); ++ if (i == 0) { ++ XPUSHs(sv_2mortal(newSVnv(buf.f_bavail))); ++ XPUSHs(sv_2mortal(newSVnv(buf.f_bfree))); ++ XPUSHs(sv_2mortal(newSVnv(buf.f_blocks))); ++ XPUSHs(sv_2mortal(newSVnv(buf.f_bsize))); ++ XPUSHs(sv_2mortal(newSVnv(buf.f_ffree))); ++ XPUSHs(sv_2mortal(newSVnv(buf.f_files))); ++ XPUSHs(sv_2mortal(newSVnv(buf.f_type))); ++ } else { ++ XPUSHs(sv_2mortal(newSVnv(errno))); ++ } ++ ++You'll also need to add the following code to the top of the .xs file, just ++after the include of "XSUB.h": ++ ++ #include ++ ++Also add the following code segment to Mytest.t while incrementing the "9" ++tests to "11": ++ ++ @a = &Mytest::statfs("/blech"); ++ ok( scalar(@a) == 1 && $a[0] == 2 ); ++ @a = &Mytest::statfs("/"); ++ is( scalar(@a), 7 ); ++ ++=head2 New Things in this Example ++ ++This example added quite a few new concepts. We'll take them one at a time. ++ ++=over 4 ++ ++=item * ++ ++The INIT: directive contains code that will be placed immediately after ++the argument stack is decoded. C does not allow variable declarations at ++arbitrary locations inside a function, ++so this is usually the best way to declare local variables needed by the XSUB. ++(Alternatively, one could put the whole C section into braces, and ++put these declarations on top.) ++ ++=item * ++ ++This routine also returns a different number of arguments depending on the ++success or failure of the call to statfs. If there is an error, the error ++number is returned as a single-element array. If the call is successful, ++then a 7-element array is returned. Since only one argument is passed into ++this function, we need room on the stack to hold the 7 values which may be ++returned. ++ ++We do this by using the PPCODE: directive, rather than the CODE: directive. ++This tells B that we will be managing the return values that will be ++put on the argument stack by ourselves. ++ ++=item * ++ ++When we want to place values to be returned to the caller onto the stack, ++we use the series of macros that begin with "XPUSH". There are five ++different versions, for placing integers, unsigned integers, doubles, ++strings, and Perl scalars on the stack. In our example, we placed a ++Perl scalar onto the stack. (In fact this is the only macro which ++can be used to return multiple values.) ++ ++The XPUSH* macros will automatically extend the return stack to prevent ++it from being overrun. You push values onto the stack in the order you ++want them seen by the calling program. ++ ++=item * ++ ++The values pushed onto the return stack of the XSUB are actually mortal SV's. ++They are made mortal so that once the values are copied by the calling ++program, the SV's that held the returned values can be deallocated. ++If they were not mortal, then they would continue to exist after the XSUB ++routine returned, but would not be accessible. This is a memory leak. ++ ++=item * ++ ++If we were interested in performance, not in code compactness, in the success ++branch we would not use C macros, but C macros, and would ++pre-extend the stack before pushing the return values: ++ ++ EXTEND(SP, 7); ++ ++The tradeoff is that one needs to calculate the number of return values ++in advance (though overextending the stack will not typically hurt ++anything but memory consumption). ++ ++Similarly, in the failure branch we could use C I extending ++the stack: the Perl function reference comes to an XSUB on the stack, thus ++the stack is I large enough to take one return value. ++ ++=back ++ ++=head2 EXAMPLE 6 ++ ++In this example, we will accept a reference to an array as an input ++parameter, and return a reference to an array of hashes. This will ++demonstrate manipulation of complex Perl data types from an XSUB. ++ ++This extension is somewhat contrived. It is based on the code in ++the previous example. It calls the statfs function multiple times, ++accepting a reference to an array of filenames as input, and returning ++a reference to an array of hashes containing the data for each of the ++filesystems. ++ ++Return to the Mytest directory and add the following code to the end of ++Mytest.xs: ++ ++ SV * ++ multi_statfs(paths) ++ SV * paths ++ INIT: ++ AV * results; ++ SSize_t numpaths = 0, n; ++ int i; ++ struct statfs buf; ++ ++ SvGETMAGIC(paths); ++ if ((!SvROK(paths)) ++ || (SvTYPE(SvRV(paths)) != SVt_PVAV) ++ || ((numpaths = av_top_index((AV *)SvRV(paths))) < 0)) ++ { ++ XSRETURN_UNDEF; ++ } ++ results = (AV *)sv_2mortal((SV *)newAV()); ++ CODE: ++ for (n = 0; n <= numpaths; n++) { ++ HV * rh; ++ STRLEN l; ++ char * fn = SvPV(*av_fetch((AV *)SvRV(paths), n, 0), l); ++ ++ i = statfs(fn, &buf); ++ if (i != 0) { ++ av_push(results, newSVnv(errno)); ++ continue; ++ } ++ ++ rh = (HV *)sv_2mortal((SV *)newHV()); ++ ++ hv_store(rh, "f_bavail", 8, newSVnv(buf.f_bavail), 0); ++ hv_store(rh, "f_bfree", 7, newSVnv(buf.f_bfree), 0); ++ hv_store(rh, "f_blocks", 8, newSVnv(buf.f_blocks), 0); ++ hv_store(rh, "f_bsize", 7, newSVnv(buf.f_bsize), 0); ++ hv_store(rh, "f_ffree", 7, newSVnv(buf.f_ffree), 0); ++ hv_store(rh, "f_files", 7, newSVnv(buf.f_files), 0); ++ hv_store(rh, "f_type", 6, newSVnv(buf.f_type), 0); ++ ++ av_push(results, newRV_inc((SV *)rh)); ++ } ++ RETVAL = newRV_inc((SV *)results); ++ OUTPUT: ++ RETVAL ++ ++And add the following code to Mytest.t, while incrementing the "11" ++tests to "13": ++ ++ $results = Mytest::multi_statfs([ '/', '/blech' ]); ++ ok( ref $results->[0] ); ++ ok( ! ref $results->[1] ); ++ ++=head2 New Things in this Example ++ ++There are a number of new concepts introduced here, described below: ++ ++=over 4 ++ ++=item * ++ ++This function does not use a typemap. Instead, we declare it as accepting ++one SV* (scalar) parameter, and returning an SV* value, and we take care of ++populating these scalars within the code. Because we are only returning ++one value, we don't need a C directive - instead, we use C ++and C directives. ++ ++=item * ++ ++When dealing with references, it is important to handle them with caution. ++The C block first calls SvGETMAGIC(paths), in case ++paths is a tied variable. Then it checks that C returns ++true, which indicates that paths is a valid reference. (Simply ++checking C won't trigger FETCH on a tied variable.) It ++then verifies that the object referenced by paths is an array, using C ++to dereference paths, and C to discover its type. As an added test, ++it checks that the array referenced by paths is non-empty, using the ++C function (which returns -1 if the array is empty). The ++XSRETURN_UNDEF macro is used to abort the XSUB and return the undefined value ++whenever all three of these conditions are not met. ++ ++=item * ++ ++We manipulate several arrays in this XSUB. Note that an array is represented ++internally by an AV* pointer. The functions and macros for manipulating ++arrays are similar to the functions in Perl: C returns the ++highest index in an AV*, much like $#array; C fetches a single scalar ++value from an array, given its index; C pushes a scalar value onto the ++end of the array, automatically extending the array as necessary. ++ ++Specifically, we read pathnames one at a time from the input array, and ++store the results in an output array (results) in the same order. If ++statfs fails, the element pushed onto the return array is the value of ++errno after the failure. If statfs succeeds, though, the value pushed ++onto the return array is a reference to a hash containing some of the ++information in the statfs structure. ++ ++As with the return stack, it would be possible (and a small performance win) ++to pre-extend the return array before pushing data into it, since we know ++how many elements we will return: ++ ++ av_extend(results, numpaths); ++ ++=item * ++ ++We are performing only one hash operation in this function, which is storing ++a new scalar under a key using C. A hash is represented by an HV* ++pointer. Like arrays, the functions for manipulating hashes from an XSUB ++mirror the functionality available from Perl. See L and L ++for details. ++ ++=item * ++ ++To create a reference, we use the C function. Note that you can ++cast an AV* or an HV* to type SV* in this case (and many others). This ++allows you to take references to arrays, hashes and scalars with the same ++function. Conversely, the C function always returns an SV*, which may ++need to be cast to the appropriate type if it is something other than a ++scalar (check with C). ++ ++=item * ++ ++At this point, xsubpp is doing very little work - the differences between ++Mytest.xs and Mytest.c are minimal. ++ ++=back ++ ++=head2 EXAMPLE 7 (Coming Soon) ++ ++XPUSH args AND set RETVAL AND assign return value to array ++ ++=head2 EXAMPLE 8 (Coming Soon) ++ ++Setting $! ++ ++=head2 EXAMPLE 9 Passing open files to XSes ++ ++You would think passing files to an XS is difficult, with all the ++typeglobs and stuff. Well, it isn't. ++ ++Suppose that for some strange reason we need a wrapper around the ++standard C library function C. This is all we need: ++ ++ #define PERLIO_NOT_STDIO 0 ++ #define PERL_NO_GET_CONTEXT ++ #include "EXTERN.h" ++ #include "perl.h" ++ #include "XSUB.h" ++ ++ #include ++ ++ int ++ fputs(s, stream) ++ char * s ++ FILE * stream ++ ++The real work is done in the standard typemap. ++ ++B you lose all the fine stuff done by the perlio layers. This ++calls the stdio function C, which knows nothing about them. ++ ++The standard typemap offers three variants of PerlIO *: ++C (T_IN), C (T_INOUT) and C ++(T_OUT). A bare C is considered a T_INOUT. If it matters ++in your code (see below for why it might) #define or typedef ++one of the specific names and use that as the argument or result ++type in your XS file. ++ ++The standard typemap does not contain PerlIO * before perl 5.7, ++but it has the three stream variants. Using a PerlIO * directly ++is not backwards compatible unless you provide your own typemap. ++ ++For streams coming I perl the main difference is that ++C will get the output PerlIO * - which may make ++a difference on a socket. Like in our example... ++ ++For streams being handed I perl a new file handle is created ++(i.e. a reference to a new glob) and associated with the PerlIO * ++provided. If the read/write state of the PerlIO * is not correct then you ++may get errors or warnings from when the file handle is used. ++So if you opened the PerlIO * as "w" it should really be an ++C if open as "r" it should be an C. ++ ++Now, suppose you want to use perlio layers in your XS. We'll use the ++perlio C function as an example. ++ ++In the C part of the XS file (above the first MODULE line) you ++have ++ ++ #define OutputStream PerlIO * ++ or ++ typedef PerlIO * OutputStream; ++ ++ ++And this is the XS code: ++ ++ int ++ perlioputs(s, stream) ++ char * s ++ OutputStream stream ++ CODE: ++ RETVAL = PerlIO_puts(stream, s); ++ OUTPUT: ++ RETVAL ++ ++We have to use a C section because C has the arguments ++reversed compared to C, and we want to keep the arguments the same. ++ ++Wanting to explore this thoroughly, we want to use the stdio C ++on a PerlIO *. This means we have to ask the perlio system for a stdio ++C: ++ ++ int ++ perliofputs(s, stream) ++ char * s ++ OutputStream stream ++ PREINIT: ++ FILE *fp = PerlIO_findFILE(stream); ++ CODE: ++ if (fp != (FILE*) 0) { ++ RETVAL = fputs(s, fp); ++ } else { ++ RETVAL = -1; ++ } ++ OUTPUT: ++ RETVAL ++ ++Note: C will search the layers for a stdio ++layer. If it can't find one, it will call C to ++generate a new stdio C. Please only call C if ++you want a I C. It will generate one on each call and push a ++new stdio layer. So don't call it repeatedly on the same ++file. C will retrieve the stdio layer once it has been ++generated by C. ++ ++This applies to the perlio system only. For versions before 5.7, ++C is equivalent to C. ++ ++=head2 Troubleshooting these Examples ++ ++As mentioned at the top of this document, if you are having problems with ++these example extensions, you might see if any of these help you. ++ ++=over 4 ++ ++=item * ++ ++In versions of 5.002 prior to the gamma version, the test script in Example ++1 will not function properly. You need to change the "use lib" line to ++read: ++ ++ use lib './blib'; ++ ++=item * ++ ++In versions of 5.002 prior to version 5.002b1h, the test.pl file was not ++automatically created by h2xs. This means that you cannot say "make test" ++to run the test script. You will need to add the following line before the ++"use extension" statement: ++ ++ use lib './blib'; ++ ++=item * ++ ++In versions 5.000 and 5.001, instead of using the above line, you will need ++to use the following line: ++ ++ BEGIN { unshift(@INC, "./blib") } ++ ++=item * ++ ++This document assumes that the executable named "perl" is Perl version 5. ++Some systems may have installed Perl version 5 as "perl5". ++ ++=back ++ ++=head1 See also ++ ++For more information, consult L, L, L, L, ++and L. ++ ++=head1 Author ++ ++Jeff Okamoto > ++ ++Reviewed and assisted by Dean Roehrich, Ilya Zakharevich, Andreas Koenig, ++and Tim Bunce. ++ ++PerlIO material contributed by Lupe Christoph, with some clarification ++by Nick Ing-Simmons. ++ ++Changes for h2xs as of Perl 5.8.x by Renee Baecker ++ ++=head2 Last Changed ++ ++2012-01-20 +diff --git a/lib/perlxstypemap.pod b/lib/perlxstypemap.pod +new file mode 100644 +index 0000000..7d1f73c +--- /dev/null ++++ b/lib/perlxstypemap.pod +@@ -0,0 +1,711 @@ ++=head1 NAME ++ ++perlxstypemap - Perl XS C/Perl type mapping ++ ++=head1 DESCRIPTION ++ ++The more you think about interfacing between two languages, the more ++you'll realize that the majority of programmer effort has to go into ++converting between the data structures that are native to either of ++the languages involved. This trumps other matter such as differing ++calling conventions because the problem space is so much greater. ++There are simply more ways to shove data into memory than there are ++ways to implement a function call. ++ ++Perl XS' attempt at a solution to this is the concept of typemaps. ++At an abstract level, a Perl XS typemap is nothing but a recipe for ++converting from a certain Perl data structure to a certain C ++data structure and vice versa. Since there can be C types that ++are sufficiently similar to one another to warrant converting with ++the same logic, XS typemaps are represented by a unique identifier, ++henceforth called an B in this document. You can then tell ++the XS compiler that multiple C types are to be mapped with the same ++XS typemap. ++ ++In your XS code, when you define an argument with a C type or when ++you are using a C and an C section together with a ++C return type of your XSUB, it'll be the typemapping mechanism that ++makes this easy. ++ ++=head2 Anatomy of a typemap ++ ++In more practical terms, the typemap is a collection of code ++fragments which are used by the B compiler to map C function ++parameters and values to Perl values. The typemap file may consist ++of three sections labelled C, C, and C. ++An unlabelled initial section is assumed to be a C 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 C, C, or ++C must begin in the first column on a line by themselves, ++and must be in uppercase. ++ ++Each type of section can appear an arbitrary number of times ++and does not have to appear at all. For example, a typemap may ++commonly lack C and C sections if all it needs to ++do is associate additional C types with core XS types like T_PTROBJ. ++Lines that start with a hash C<#> are considered comments and ignored ++in the C section, but are considered significant in C ++and C. Blank lines are generally ignored. ++ ++Traditionally, typemaps needed to be written to a separate file, ++conventionally called C in a CPAN distribution. With ++ExtUtils::ParseXS (the XS compiler) version 3.12 or better which ++comes with perl 5.16, typemaps can also be embedded directly into ++XS code using a HERE-doc like syntax: ++ ++ TYPEMAP: < can be replaced by other identifiers like with normal ++Perl HERE-docs. All details below about the typemap textual format ++remain valid. ++ ++The C section should contain one pair of C type and ++XS type per line as follows. An example from the core typemap file: ++ ++ TYPEMAP ++ # all variants of char* is handled by the T_PV typemap ++ char * T_PV ++ const char * T_PV ++ unsigned char * T_PV ++ ... ++ ++The C and C sections have identical formats, that is, ++each unindented line starts a new in- or output map respectively. ++A new in- or output map must start with the name of the XS type to ++map on a line by itself, followed by the code that implements it ++indented on the following lines. Example: ++ ++ INPUT ++ T_PV ++ $var = ($type)SvPV_nolen($arg) ++ T_PTR ++ $var = INT2PTR($type,SvIV($arg)) ++ ++We'll get to the meaning of those Perlish-looking variables in a ++little bit. ++ ++Finally, here's an example of the full typemap file for mapping C ++strings of the C type to Perl scalars/strings: ++ ++ TYPEMAP ++ char * T_PV ++ ++ INPUT ++ T_PV ++ $var = ($type)SvPV_nolen($arg) ++ ++ OUTPUT ++ T_PV ++ sv_setpv((SV*)$arg, $var); ++ ++Here's a more complicated example: suppose that you wanted ++C to be blessed into the class C. ++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 that maps ++underscores to double-colons (::), and declare C 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 C 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 C, C, C macros, ++to map the other way, which may be useful in OUTPUT sections. ++ ++=head2 The Role of the typemap File in Your Distribution ++ ++The default typemap in the F 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 compiler will allow the extension's own typemap to ++override any mappings which are in the default typemap. Instead of using ++an additional F file, typemaps may be embedded verbatim in XS ++with a heredoc-like syntax. See the documentation on the C XS ++keyword. ++ ++For CPAN distributions, you can assume that the XS types defined by ++the perl core are already available. Additionally, the core typemap ++has default XS types for a large number of C types. For example, if ++you simply return a C from your XSUB, the core typemap will ++have this C type associated with the T_PV XS type. That means your ++C string will be copied into the PV (pointer value) slot of a new scalar ++that will be returned from your XSUB to Perl. ++ ++If you're developing a CPAN distribution using XS, you may add your own ++file called F to the distribution. That file may contain ++typemaps that either map types that are specific to your code or that ++override the core typemap file's mappings for common C types. ++ ++=head2 Sharing typemaps Between CPAN Distributions ++ ++Starting with ExtUtils::ParseXS version 3.13_01 (comes with perl 5.16 ++and better), it is rather easy to share typemap code between multiple ++CPAN distributions. The general idea is to share it as a module that ++offers a certain API and have the dependent modules declare that as a ++built-time requirement and import the typemap into the XS. An example ++of such a typemap-sharing module on CPAN is ++C. Two steps to getting that module's ++typemaps available in your code: ++ ++=over 4 ++ ++=item * ++ ++Declare C as a build-time dependency ++in C (use C), or in your C ++(use C). ++ ++=item * ++ ++Include the following line in the XS section of your XS file: ++(don't break the line) ++ ++ INCLUDE_COMMAND: $^X -MExtUtils::Typemaps::Cmd ++ -e "print embeddable_typemap(q{Basic})" ++ ++=back ++ ++=head2 Writing typemap Entries ++ ++Each INPUT or OUTPUT typemap entry is a double-quoted Perl string that ++will be evaluated in the presence of certain variables to get the ++final C code for mapping a certain C type. ++ ++This means that you can embed Perl code in your typemap (C) code using ++constructs such as ++C<${ perl code that evaluates to scalar reference here }>. A common ++use case is to generate error messages that refer to the true function ++name even when using the ALIAS XS feature: ++ ++ ${ $ALIAS ? \q[GvNAME(CvGV(cv))] : \qq[\"$pname\"] } ++ ++For many typemap examples, refer to the core typemap file that can be ++found in the perl source tree at F. ++ ++The Perl variables that are available for interpolation into typemaps ++are the following: ++ ++=over 4 ++ ++=item * ++ ++I<$var> - the name of the input or output variable, eg. RETVAL for ++return values. ++ ++=item * ++ ++I<$type> - the raw C type of the parameter, any C<:> replaced with ++C<_>. ++e.g. for a type of C, I<$type> is C ++ ++=item * ++ ++I<$ntype> - the supplied type with C<*> replaced with C. ++e.g. for a type of C, I<$ntype> is C ++ ++=item * ++ ++I<$arg> - the stack entry, that the parameter is input from or output ++to, e.g. C ++ ++=item * ++ ++I<$argoff> - the argument stack offset of the argument. ie. 0 for the ++first argument, etc. ++ ++=item * ++ ++I<$pname> - the full name of the XSUB, with including the C ++name, with any C stripped. This is the non-ALIAS name. ++ ++=item * ++ ++I<$Package> - the package specified by the most recent C ++keyword. ++ ++=item * ++ ++I<$ALIAS> - non-zero if the current XSUB has any aliases declared with ++C. ++ ++=back ++ ++=head2 Full Listing of Core Typemaps ++ ++Each C type is represented by an entry in the typemap file that ++is responsible for converting perl variables (SV, AV, HV, CV, etc.) ++to and from that type. The following sections list all XS types ++that come with perl by default. ++ ++=over 4 ++ ++=item T_SV ++ ++This simply passes the C representation of the Perl variable (an SV*) ++in and out of the XS layer. This can be used if the C code wants ++to deal directly with the Perl variable. ++ ++=item T_SVREF ++ ++Used to pass in and return a reference to an SV. ++ ++Note that this typemap does not decrement the reference count ++when returning the reference to an SV*. ++See also: T_SVREF_REFCOUNT_FIXED ++ ++=item T_SVREF_FIXED ++ ++Used to pass in and return a reference to an SV. ++This is a fixed ++variant of T_SVREF that decrements the refcount appropriately ++when returning a reference to an SV*. Introduced in perl 5.15.4. ++ ++=item T_AVREF ++ ++From the perl level this is a reference to a perl array. ++From the C level this is a pointer to an AV. ++ ++Note that this typemap does not decrement the reference count ++when returning an AV*. See also: T_AVREF_REFCOUNT_FIXED ++ ++=item T_AVREF_REFCOUNT_FIXED ++ ++From the perl level this is a reference to a perl array. ++From the C level this is a pointer to an AV. This is a fixed ++variant of T_AVREF that decrements the refcount appropriately ++when returning an AV*. Introduced in perl 5.15.4. ++ ++=item T_HVREF ++ ++From the perl level this is a reference to a perl hash. ++From the C level this is a pointer to an HV. ++ ++Note that this typemap does not decrement the reference count ++when returning an HV*. See also: T_HVREF_REFCOUNT_FIXED ++ ++=item T_HVREF_REFCOUNT_FIXED ++ ++From the perl level this is a reference to a perl hash. ++From the C level this is a pointer to an HV. This is a fixed ++variant of T_HVREF that decrements the refcount appropriately ++when returning an HV*. Introduced in perl 5.15.4. ++ ++=item T_CVREF ++ ++From the perl level this is a reference to a perl subroutine ++(e.g. $sub = sub { 1 };). From the C level this is a pointer ++to a CV. ++ ++Note that this typemap does not decrement the reference count ++when returning an HV*. See also: T_HVREF_REFCOUNT_FIXED ++ ++=item T_CVREF_REFCOUNT_FIXED ++ ++From the perl level this is a reference to a perl subroutine ++(e.g. $sub = sub { 1 };). From the C level this is a pointer ++to a CV. ++ ++This is a fixed ++variant of T_HVREF that decrements the refcount appropriately ++when returning an HV*. Introduced in perl 5.15.4. ++ ++=item T_SYSRET ++ ++The T_SYSRET typemap is used to process return values from system calls. ++It is only meaningful when passing values from C to perl (there is ++no concept of passing a system return value from Perl to C). ++ ++System calls return -1 on error (setting ERRNO with the reason) ++and (usually) 0 on success. If the return value is -1 this typemap ++returns C. If the return value is not -1, this typemap ++translates a 0 (perl false) to "0 but true" (which ++is perl true) or returns the value itself, to indicate that the ++command succeeded. ++ ++The L module makes extensive use of this type. ++ ++=item T_UV ++ ++An unsigned integer. ++ ++=item T_IV ++ ++A signed integer. This is cast to the required integer type when ++passed to C and converted to an IV when passed back to Perl. ++ ++=item T_INT ++ ++A signed integer. This typemap converts the Perl value to a native ++integer type (the C type on the current platform). When returning ++the value to perl it is processed in the same way as for T_IV. ++ ++Its behaviour is identical to using an C type in XS with T_IV. ++ ++=item T_ENUM ++ ++An enum value. Used to transfer an enum component ++from C. There is no reason to pass an enum value to C since ++it is stored as an IV inside perl. ++ ++=item T_BOOL ++ ++A boolean type. This can be used to pass true and false values to and ++from C. ++ ++=item T_U_INT ++ ++This is for unsigned integers. It is equivalent to using T_UV ++but explicitly casts the variable to type C. ++The default type for C is T_UV. ++ ++=item T_SHORT ++ ++Short integers. This is equivalent to T_IV but explicitly casts ++the return to type C. The default typemap for C ++is T_IV. ++ ++=item T_U_SHORT ++ ++Unsigned short integers. This is equivalent to T_UV but explicitly ++casts the return to type C. The default typemap for ++C is T_UV. ++ ++T_U_SHORT is used for type C in the standard typemap. ++ ++=item T_LONG ++ ++Long integers. This is equivalent to T_IV but explicitly casts ++the return to type C. The default typemap for C ++is T_IV. ++ ++=item T_U_LONG ++ ++Unsigned long integers. This is equivalent to T_UV but explicitly ++casts the return to type C. The default typemap for ++C is T_UV. ++ ++T_U_LONG is used for type C in the standard typemap. ++ ++=item T_CHAR ++ ++Single 8-bit characters. ++ ++=item T_U_CHAR ++ ++An unsigned byte. ++ ++=item T_FLOAT ++ ++A floating point number. This typemap guarantees to return a variable ++cast to a C. ++ ++=item T_NV ++ ++A Perl floating point number. Similar to T_IV and T_UV in that the ++return type is cast to the requested numeric type rather than ++to a specific type. ++ ++=item T_DOUBLE ++ ++A double precision floating point number. This typemap guarantees to ++return a variable cast to a C. ++ ++=item T_PV ++ ++A string (char *). ++ ++=item T_PTR ++ ++A memory address (pointer). Typically associated with a C ++type. ++ ++=item T_PTRREF ++ ++Similar to T_PTR except that the pointer is stored in a scalar and the ++reference to that scalar is returned to the caller. This can be used ++to hide the actual pointer value from the programmer since it is usually ++not required directly from within perl. ++ ++The typemap checks that a scalar reference is passed from perl to XS. ++ ++=item T_PTROBJ ++ ++Similar to T_PTRREF except that the reference is blessed into a class. ++This allows the pointer to be used as an object. Most commonly used to ++deal with C structs. The typemap checks that the perl object passed ++into the XS routine is of the correct class (or part of a subclass). ++ ++The pointer is blessed into a class that is derived from the name ++of type of the pointer but with all '*' in the name replaced with ++'Ptr'. ++ ++For C XSUBs only, a T_PTROBJ is optimized to a T_PTRREF. This means ++the class check is skipped. ++ ++=item T_REF_IV_REF ++ ++NOT YET ++ ++=item T_REF_IV_PTR ++ ++Similar to T_PTROBJ in that the pointer is blessed into a scalar object. ++The difference is that when the object is passed back into XS it must be ++of the correct type (inheritance is not supported) while T_PTROBJ supports ++inheritance. ++ ++The pointer is blessed into a class that is derived from the name ++of type of the pointer but with all '*' in the name replaced with ++'Ptr'. ++ ++For C XSUBs only, a T_REF_IV_PTR is optimized to a T_PTRREF. This ++means the class check is skipped. ++ ++=item T_PTRDESC ++ ++NOT YET ++ ++=item T_REFREF ++ ++Similar to T_PTRREF, except the pointer stored in the referenced scalar ++is dereferenced and copied to the output variable. This means that ++T_REFREF is to T_PTRREF as T_OPAQUE is to T_OPAQUEPTR. All clear? ++ ++Only the INPUT part of this is implemented (Perl to XSUB) and there ++are no known users in core or on CPAN. ++ ++=item T_REFOBJ ++ ++Like T_REFREF, except it does strict type checking (inheritance is not ++supported). ++ ++For C XSUBs only, a T_REFOBJ is optimized to a T_REFREF. This means ++the class check is skipped. ++ ++=item T_OPAQUEPTR ++ ++This can be used to store bytes in the string component of the ++SV. Here the representation of the data is irrelevant to perl and the ++bytes themselves are just stored in the SV. It is assumed that the C ++variable is a pointer (the bytes are copied from that memory ++location). If the pointer is pointing to something that is ++represented by 8 bytes then those 8 bytes are stored in the SV (and ++length() will report a value of 8). This entry is similar to T_OPAQUE. ++ ++In principle the unpack() command can be used to convert the bytes ++back to a number (if the underlying type is known to be a number). ++ ++This entry can be used to store a C structure (the number ++of bytes to be copied is calculated using the C C function) ++and can be used as an alternative to T_PTRREF without having to worry ++about a memory leak (since Perl will clean up the SV). ++ ++=item T_OPAQUE ++ ++This can be used to store data from non-pointer types in the string ++part of an SV. It is similar to T_OPAQUEPTR except that the ++typemap retrieves the pointer directly rather than assuming it ++is being supplied. For example, if an integer is imported into ++Perl using T_OPAQUE rather than T_IV the underlying bytes representing ++the integer will be stored in the SV but the actual integer value will ++not be available. i.e. The data is opaque to perl. ++ ++The data may be retrieved using the C function if the ++underlying type of the byte stream is known. ++ ++T_OPAQUE supports input and output of simple types. ++T_OPAQUEPTR can be used to pass these bytes back into C if a pointer ++is acceptable. ++ ++=item Implicit array ++ ++xsubpp supports a special syntax for returning ++packed C arrays to perl. If the XS return type is given as ++ ++ array(type, nelem) ++ ++xsubpp will copy the contents of C bytes from ++RETVAL to an SV and push it onto the stack. This is only really useful ++if the number of items to be returned is known at compile time and you ++don't mind having a string of bytes in your SV. Use T_ARRAY to push a ++variable number of arguments onto the return stack (they won't be ++packed as a single string though). ++ ++This is similar to using T_OPAQUEPTR but can be used to process more ++than one element. ++ ++=item T_PACKED ++ ++Calls user-supplied functions for conversion. For C ++(XSUB to Perl), a function named C is called ++with the output Perl scalar and the C variable to convert from. ++C<$ntype> is the normalized C type that is to be mapped to ++Perl. Normalized means that all C<*> are replaced by the ++string C. The return value of the function is ignored. ++ ++Conversely for C (Perl to XSUB) mapping, the ++function named C is called with the input Perl ++scalar as argument and the return value is cast to the mapped ++C type and assigned to the output C variable. ++ ++An example conversion function for a typemapped struct ++C might be: ++ ++ static void ++ XS_pack_foo_tPtr(SV *out, foo_t *in) ++ { ++ dTHX; /* alas, signature does not include pTHX_ */ ++ HV* hash = newHV(); ++ hv_stores(hash, "int_member", newSViv(in->int_member)); ++ hv_stores(hash, "float_member", newSVnv(in->float_member)); ++ /* ... */ ++ ++ /* mortalize as thy stack is not refcounted */ ++ sv_setsv(out, sv_2mortal(newRV_noinc((SV*)hash))); ++ } ++ ++The conversion from Perl to C is left as an exercise to the reader, ++but the prototype would be: ++ ++ static foo_t * ++ XS_unpack_foo_tPtr(SV *in); ++ ++Instead of an actual C function that has to fetch the thread context ++using C, you can define macros of the same name and avoid the ++overhead. Also, keep in mind to possibly free the memory allocated by ++C. ++ ++=item T_PACKEDARRAY ++ ++T_PACKEDARRAY is similar to T_PACKED. In fact, the C (Perl ++to XSUB) typemap is identical, but the C typemap passes ++an additional argument to the C function. This ++third parameter indicates the number of elements in the output ++so that the function can handle C arrays sanely. The variable ++needs to be declared by the user and must have the name ++C where C<$ntype> is the normalized C type name ++as explained above. The signature of the function would be for ++the example above and C: ++ ++ static void ++ XS_pack_foo_tPtrPtr(SV *out, foo_t *in, UV count_foo_tPtrPtr); ++ ++The type of the third parameter is arbitrary as far as the typemap ++is concerned. It just has to be in line with the declared variable. ++ ++Of course, unless you know the number of elements in the ++C C array, within your XSUB, the return value from ++C will be hard to decipher. ++Since the details are all up to the XS author (the typemap user), ++there are several solutions, none of which particularly elegant. ++The most commonly seen solution has been to allocate memory for ++N+1 pointers and assign C to the (N+1)th to facilitate ++iteration. ++ ++Alternatively, using a customized typemap for your purposes in ++the first place is probably preferable. ++ ++=item T_DATAUNIT ++ ++NOT YET ++ ++=item T_CALLBACK ++ ++NOT YET ++ ++=item T_ARRAY ++ ++This is used to convert the perl argument list to a C array ++and for pushing the contents of a C array onto the perl ++argument stack. ++ ++The usual calling signature is ++ ++ @out = array_func( @in ); ++ ++Any number of arguments can occur in the list before the array but ++the input and output arrays must be the last elements in the list. ++ ++When used to pass a perl list to C the XS writer must provide a ++function (named after the array type but with 'Ptr' substituted for ++'*') to allocate the memory required to hold the list. A pointer ++should be returned. It is up to the XS writer to free the memory on ++exit from the function. The variable C is set to the number ++of elements in the new array. ++ ++When returning a C array to Perl the XS writer must provide an integer ++variable called C containing the number of elements in the ++array. This is used to determine how many elements should be pushed ++onto the return argument stack. This is not required on input since ++Perl knows how many arguments are on the stack when the routine is ++called. Ordinarily this variable would be called C. ++ ++Additionally, the type of each element is determined from the type of ++the array. If the array uses type C xsubpp will ++automatically work out that it contains variables of type C and ++use that typemap entry to perform the copy of each element. All ++pointer '*' and 'Array' tags are removed from the name to determine ++the subtype. ++ ++=item T_STDIO ++ ++This is used for passing perl filehandles to and from C using ++C structures. ++ ++=item T_INOUT ++ ++This is used for passing perl filehandles to and from C using ++C structures. The file handle can used for reading and ++writing. This corresponds to the C<+E> mode, see also T_IN ++and T_OUT. ++ ++See L for more information on the Perl IO abstraction ++layer. Perl must have been built with C<-Duseperlio>. ++ ++There is no check to assert that the filehandle passed from Perl ++to C was created with the right C mode. ++ ++Hint: The L tutorial covers the T_INOUT, T_IN, and T_OUT ++XS types nicely. ++ ++=item T_IN ++ ++Same as T_INOUT, but the filehandle that is returned from C to Perl ++can only be used for reading (mode C>). ++ ++=item T_OUT ++ ++Same as T_INOUT, but the filehandle that is returned from C to Perl ++is set to use the open mode C<+E>. ++ ++=back ++ +diff --git a/t/XSTest.xs b/t/XSTest.xs +index 89df22f..452d3db 100644 +--- a/t/XSTest.xs ++++ b/t/XSTest.xs +@@ -76,6 +76,7 @@ bool + T_BOOL_2(in) + bool in + CODE: ++ PERL_UNUSED_VAR(RETVAL); + OUTPUT: in + + void +diff --git a/t/XSUsage.xs b/t/XSUsage.xs +index 9a8d93d..ed3c8f8 100644 +--- a/t/XSUsage.xs ++++ b/t/XSUsage.xs +@@ -35,6 +35,8 @@ xsusage_two() + ALIAS: + two_x = 1 + FOO::two = 2 ++ INIT: ++ PERL_UNUSED_VAR(ix); + + int + interface_v_i() +-- +2.14.3 + diff --git a/ExtUtils-ParseXS-3.35.tar.gz b/ExtUtils-ParseXS-3.35.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..f2fc4fc414680d2b56b5b8c3db88992e6469de45 GIT binary patch literal 68623 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 Ne*@DKkNp7H1OO?${)7Mk literal 0 HcmV?d00001 diff --git a/perl-ExtUtils-ParseXS.spec b/perl-ExtUtils-ParseXS.spec new file mode 100644 index 0000000..f525419 --- /dev/null +++ b/perl-ExtUtils-ParseXS.spec @@ -0,0 +1,61 @@ +Name: perl-ExtUtils-ParseXS +Epoch: 1 +Version: 3.39 +Release: 419 +Summary: Convert Perl XS code into C code +License: GPL+ or Artistic +URL: https://metacpan.org/pod/ExtUtils::ParseXS +Source0: https://cpan.metacpan.org/authors/id/S/SM/SMUELLER/ExtUtils-ParseXS-3.35.tar.gz + +Patch0: ExtUtils-ParseXS-3.35-Upgrade-to-3.39.patch +BuildArch: noarch +BuildRequires: gcc git coreutils make perl-devel perl-generators perl-interpreter perl(Config) +BuildRequires: perl(ExtUtils::MakeMaker) >= 6.76 perl(File::Spec) perl(strict) perl(warnings) +BuildRequires: perl(Cwd) perl(Exporter) >= 5.57 perl(File::Basename) perl(re) perl(Symbol) +BuildRequires: perl(attributes) perl(Carp) perl(DynaLoader) perl(ExtUtils::CBuilder) +BuildRequires: perl(File::Temp) perl(lib) perl(overload) perl(Test::More) >= 0.47 +Requires: perl(:MODULE_COMPAT_%(eval "`perl -V:version`"; echo $version)) perl(Exporter) >= 5.57 + +%global __requires_exclude %{?__requires_exclude:%__requires_exclude|}^perl\\(Exporter\\)$ + +%description +ExtUtils::ParseXS will compile XS code into C code by embedding the constructs necessary to let C functions manipulate Perl values +and creates the glue necessary to let Perl access those functions. +The compiler uses typemaps to determine how to map C function parameters and variables to Perl values. + +%package_help + +%prep +%autosetup -n ExtUtils-ParseXS-3.35 -p1 + +%build +perl Makefile.PL INSTALLDIRS=vendor NO_PACKLIST=1 NO_PERLLOCAL=1 +%make_build + +%install +%make_install +%{_fixperms} $RPM_BUILD_ROOT/* +rm $RPM_BUILD_ROOT%{perl_vendorlib}/ExtUtils/xsubpp +ln -s ../../../../bin/xsubpp $RPM_BUILD_ROOT%{perl_vendorlib}/ExtUtils/ + +%check +make test + +%files +%doc Changes README +%{_bindir}/* +%{perl_vendorlib}/* + +%files help +%{_mandir}/man1/* +%{_mandir}/man3/* + +%changelog +* Sun Sep 29 2019 openEuler Buildteam - 1:3.39-419 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC: revise changelog + +* Sat Sep 14 2019 shidongdong - 1:3.39-418 +- Package init