diff options
Diffstat (limited to 'pod/perlapi.pod')
-rw-r--r-- | pod/perlapi.pod | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/pod/perlapi.pod b/pod/perlapi.pod new file mode 100644 index 0000000000..f76d877f9b --- /dev/null +++ b/pod/perlapi.pod @@ -0,0 +1,951 @@ +=head1 NAME + +perlapi - Perl 5 application programming interface for C extensions + +=head1 DESCRIPTION + +=head2 Introduction + +XS is a language used to create an extension interface +between Perl and some C library which one wishes to use with +Perl. The XS interface is combined with the library to +create a new library which can be linked to Perl. An B<XSUB> +is a function in the XS language and is the core component +of the Perl application interface. + +The XS compiler is called B<xsubpp>. This compiler will embed +the constructs necessary to let an XSUB, which is really a C +function in disguise, manipulate Perl values and creates the +glue necessary to let Perl access the XSUB. The compiler +uses B<typemaps> to determine how to map C function parameters +and variables to Perl values. The default typemap handles +many common C types. A supplement typemap must be created +to handle special structures and types for the library being +linked. + +Many of the examples which follow will concentrate on creating an +interface between Perl and the ONC+RPC bind library functions. +Specifically, the rpcb_gettime() function will be used to demonstrate many +features of the XS language. This function has two parameters; the first +is an input parameter and the second is an output parameter. The function +also returns a status value. + + bool_t rpcb_gettime(const char *host, time_t *timep); + +From C this function will be called with the following +statements. + + #include <rpc/rpc.h> + bool_t status; + time_t timep; + status = rpcb_gettime( "localhost", &timep ); + +If an XSUB is created to offer a direct translation between this function +and Perl, then this XSUB will be used from Perl with the following code. +The $status and $timep variables will contain the output of the function. + + use RPC; + $status = rpcb_gettime( "localhost", $timep ); + +The following XS file shows an XS subroutine, or XSUB, which +demonstrates one possible interface to the rpcb_gettime() +function. This XSUB represents a direct translation between +C and Perl and so preserves the interface even from Perl. +This XSUB will be invoked from Perl with the usage shown +above. Note that the first three #include statements, for +C<EXTERN.h>, C<perl.h>, and C<XSUB.h>, will always be present at the +beginning of an XS file. This approach and others will be +expanded later in this document. + + #include "EXTERN.h" + #include "perl.h" + #include "XSUB.h" + #include <rpc/rpc.h> + + MODULE = RPC PACKAGE = RPC + + bool_t + rpcb_gettime(host,timep) + char * host + time_t &timep + OUTPUT: + timep + +Any extension to Perl, including those containing XSUBs, +should have a Perl module to serve as the bootstrap which +pulls the extension into Perl. This module will export the +extension's functions and variables to the Perl program and +will cause the extension's XSUBs to be linked into Perl. +The following module will be used for most of the examples +in this document and should be used from Perl with the C<use> +command as shown earlier. Perl modules are explained in +more detail later in this document. + + package RPC; + + require Exporter; + require DynaLoader; + @ISA = qw(Exporter DynaLoader); + @EXPORT = qw( rpcb_gettime ); + + bootstrap RPC; + 1; + +Throughout this document a variety of interfaces to the rpcb_gettime() +XSUB will be explored. The XSUBs will take their parameters in different +orders or will take different numbers of parameters. In each case the +XSUB is an abstraction between Perl and the real C rpcb_gettime() +function, and the XSUB must always ensure that the real rpcb_gettime() +function is called with the correct parameters. This abstraction will +allow the programmer to create a more Perl-like interface to the C +function. + +=head2 The Anatomy of an XSUB + +The following XSUB allows a Perl program to access a C library function called sin(). The XSUB will imitate the C +function which takes a single argument and returns a single +value. + + double + sin(x) + double<tab>x + +The compiler expects a tab between the parameter name and its type, and +any or no whitespace before the type. When using C pointers the +indirection operator C<*> should be considered part of the type and the +address operator C<&> should be considered part of the variable, as is +demonstrated in the rpcb_gettime() function above. See the section on +typemaps for more about handling qualifiers and unary operators in C +types. + +The parameter list of a function must not have whitespace +after the open-parenthesis or before the close-parenthesis. + + INCORRECT CORRECT + + double double + sin( x ) sin(x) + double x double x + +The function name and the return type must be placed on +separate lines. + + INCORRECT CORRECT + + double sin(x) double + double x sin(x) + double x + +=head2 The Argument Stack + +The argument stack is used to store the values which are +sent as parameters to the XSUB and to store the XSUB's +return value. In reality all Perl functions keep their +values on this stack at the same time, each limited to its +own range of positions on the stack. In this document the +first position on that stack which belongs to the active +function will be referred to as position 0 for that function. + +XSUBs refer to their stack arguments with the macro B<ST(x)>, where I<x> refers +to a position in this XSUB's part of the stack. Position 0 for that +function would be known to the XSUB as ST(0). The XSUB's incoming +parameters and outgoing return values always begin at ST(0). For many +simple cases the B<xsubpp> compiler will generate the code necessary to +handle the argument stack by embedding code fragments found in the +typemaps. In more complex cases the programmer must supply the code. + +=head2 The RETVAL Variable + +The RETVAL variable is a magic variable which always matches +the return type of the C library function. The B<xsubpp> compiler will +supply this variable in each XSUB and by default will use it to hold the +return value of the C library function being called. In simple cases the +value of RETVAL will be placed in ST(0) of the argument stack where it can +be received by Perl as the return value of the XSUB. + +If the XSUB has a return type of C<void> then the compiler will +not supply a RETVAL variable for that function. When using +the PPCODE: directive the RETVAL variable may not be needed. + +=head2 The MODULE Keyword + +The MODULE keyword is used to start the XS code and to +specify the package of the functions which are being +defined. All text preceding the first MODULE keyword is +considered C code and is passed through to the output +untouched. Every XS module will have a bootstrap function +which is used to hook the XSUBs into Perl. The package name +of this bootstrap function will match the value of the last +MODULE statement in the XS source files. The value of +MODULE should always remain constant within the same XS +file, though this is not required. + +The following example will start the XS code and will place +all functions in a package named RPC. + + MODULE = RPC + +=head2 The PACKAGE Keyword + +When functions within an XS source file must be separated into packages +the PACKAGE keyword should be used. This keyword is used with the MODULE +keyword and must follow immediately after it when used. + + MODULE = RPC PACKAGE = RPC + + [ XS code in package RPC ] + + MODULE = RPC PACKAGE = RPCB + + [ XS code in package RPCB ] + + MODULE = RPC PACKAGE = RPC + + [ XS code in package RPC ] + +Although this keyword is optional and in some cases provides redundant +information it should always be used. This keyword will ensure that the +XSUBs appear in the desired package. + +=head2 The PREFIX Keyword + +The PREFIX keyword designates prefixes which should be +removed from the Perl function names. If the C function is +C<rpcb_gettime()> and the PREFIX value is C<rpcb_> then Perl will +see this function as C<gettime()>. + +This keyword should follow the PACKAGE keyword when used. +If PACKAGE is not used then PREFIX should follow the MODULE +keyword. + + MODULE = RPC PREFIX = rpc_ + + MODULE = RPC PACKAGE = RPCB PREFIX = rpcb_ + +=head2 The OUTPUT: Keyword + +The OUTPUT: keyword indicates that certain function parameters should be +updated (new values made visible to Perl) when the XSUB terminates or that +certain values should be returned to the calling Perl function. For +simple functions, such as the sin() function above, the RETVAL variable is +automatically designated as an output value. In more complex functions +the B<xsubpp> compiler will need help to determine which variables are output +variables. + +This keyword will normally be used to complement the CODE: keyword. +The RETVAL variable is not recognized as an output variable when the +CODE: keyword is present. The OUTPUT: keyword is used in this +situation to tell the compiler that RETVAL really is an output +variable. + +The OUTPUT: keyword can also be used to indicate that function parameters +are output variables. This may be necessary when a parameter has been +modified within the function and the programmer would like the update to +be seen by Perl. If function parameters are listed under OUTPUT: along +with the RETVAL variable then the RETVAL variable must be the last one +listed. + + 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<tab>sv_setnv(ST(1), (double)timep); + +=head2 The CODE: Keyword + +This keyword is used in more complicated XSUBs which require +special handling for the C function. The RETVAL variable is +available but will not be returned unless it is specified +under the OUTPUT: keyword. + +The following XSUB is for a C function which requires special handling of +its parameters. The Perl usage is given first. + + $status = rpcb_gettime( "localhost", $timep ); + +The XSUB follows. + + bool_t rpcb_gettime(host,timep) + char * host + time_t timep + CODE: + RETVAL = rpcb_gettime( host, &timep ); + OUTPUT: + timep + RETVAL + +In many of the examples shown here the CODE: block (and +other blocks) will often be contained within braces ( C<{> and +C<}> ). This protects the CODE: block from complex INPUT +typemaps and ensures the resulting C code is legal. + +=head2 The NO_INIT Keyword + +The NO_INIT keyword is used to indicate that a function +parameter is being used only as an output value. The B<xsubpp> +compiler will normally generate code to read the values of +all function parameters from the argument stack and assign +them to C variables upon entry to the function. NO_INIT +will tell the compiler that some parameters will be used for +output rather than for input and that they will be handled +before the function terminates. + +The following example shows a variation of the rpcb_gettime() function. +This function uses the timep variable only as an output variable and does +not care about its initial contents. + + bool_t + rpcb_gettime(host,timep) + char * host + time_t &timep = NO_INIT + OUTPUT: + timep + +=head2 Initializing Function Parameters + +Function parameters are normally initialized with their +values from the argument stack. The typemaps contain the +code segments which are used to transfer the Perl values to +the C parameters. The programmer, however, is allowed to +override the typemaps and supply alternate initialization +code. + +The following code demonstrates how to supply initialization code for +function parameters. The initialization code is eval'd by the compiler +before it is added to the output so anything which should be interpreted +literally, such as double quotes, must be protected with backslashes. + + bool_t + rpcb_gettime(host,timep) + char * host = (char *)SvPV(ST(0),na); + time_t &timep = 0; + OUTPUT: + timep + +This should not be used to supply default values for parameters. One +would normally use this when a function parameter must be processed by +another library function before it can be used. Default parameters are +covered in the next section. + +=head2 Default Parameter Values + +Default values can be specified for function parameters by +placing an assignment statement in the parameter list. The +default value may be a number or a string. Defaults should +always be used on the right-most parameters only. + +To allow the XSUB for rpcb_gettime() to have a default host +value the parameters to the XSUB could be rearranged. The +XSUB will then call the real rpcb_gettime() function with +the parameters in the correct order. Perl will call this +XSUB with either of the following statements. + + $status = rpcb_gettime( $timep, $host ); + + $status = rpcb_gettime( $timep ); + +The XSUB will look like the code which follows. A CODE: +block is used to call the real rpcb_gettime() function with +the parameters in the correct order for that function. + + bool_t + rpcb_gettime(timep,host="localhost") + char * host + time_t timep = NO_INIT + CODE: + RETVAL = rpcb_gettime( host, &timep ); + OUTPUT: + timep + RETVAL + +=head2 Variable-length Parameter Lists + +XSUBs can have variable-length parameter lists by specifying an ellipsis +C<(...)> in the parameter list. This use of the ellipsis is similar to that +found in ANSI C. The programmer is able to determine the number of +arguments passed to the XSUB by examining the C<items> variable which the +B<xsubpp> compiler supplies for all XSUBs. By using this mechanism one can +create an XSUB which accepts a list of parameters of unknown length. + +The I<host> parameter for the rpcb_gettime() XSUB can be +optional so the ellipsis can be used to indicate that the +XSUB will take a variable number of parameters. Perl should +be able to call this XSUB with either of the following statments. + + $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 + CODE: + { + char *host = "localhost"; + + if( items > 1 ) + host = (char *)SvPV(ST(1), na); + RETVAL = rpcb_gettime( host, &timep ); + } + OUTPUT: + timep + RETVAL + +=head2 The PPCODE: Keyword + +The PPCODE: keyword is an alternate form of the CODE: keyword and is used +to tell the B<xsubpp> compiler that the programmer is supplying the code to +control the argument stack for the XSUBs return values. Occassionally one +will want an XSUB to return a list of values rather than a single value. +In these cases one must use PPCODE: and then explicitly push the list of +values on the stack. The PPCODE: and CODE: keywords are not used +together within the same XSUB. + +The following XSUB will call the C rpcb_gettime() function +and will return its two output values, timep and status, to +Perl as a single list. + + void rpcb_gettime(host) + char * host + PPCODE: + { + time_t timep; + bool_t status; + status = rpcb_gettime( host, &timep ); + EXTEND(sp, 2); + PUSHs(sv_2mortal(newSVnv(status))); + PUSHs(sv_2mortal(newSVnv(timep))); + } + +Notice that the programmer must supply the C code necessary +to have the real rpcb_gettime() function called and to have +the return values properly placed on the argument stack. + +The C<void> return type for this function tells the B<xsubpp> compiler that +the RETVAL variable is not needed or used and that it should not be created. +In most scenarios the void return type should be used with the PPCODE: +directive. + +The EXTEND() macro is used to make room on the argument +stack for 2 return values. The PPCODE: directive causes the +B<xsubpp> compiler to create a stack pointer called C<sp>, and it +is this pointer which is being used in the EXTEND() macro. +The values are then pushed onto the stack with the PUSHs() +macro. + +Now the rpcb_gettime() function can be used from Perl with +the following statement. + + ($status, $timep) = rpcb_gettime("localhost"); + +=head2 Returning Undef And Empty Lists + +Occassionally the programmer will want to simply return +C<undef> or an empty list if a function fails rather than a +separate status value. The rpcb_gettime() function offers +just this situation. If the function succeeds we would like +to have it return the time and if it fails we would like to +have undef returned. In the following Perl code the value +of $timep will either be undef or it will be a valid time. + + $timep = rpcb_gettime( "localhost" ); + +The following XSUB uses the C<void> return type to disable the generation of +the RETVAL variable 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. + + void + rpcb_gettime(host) + char * host + CODE: + { + time_t timep; + bool_t x; + 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. + + void + rpcb_gettime(host) + char * host + CODE: + { + time_t timep; + bool_t x; + ST(0) = sv_newmortal(); + if( rpcb_gettime( host, &timep ) ){ + sv_setnv( ST(0), (double)timep); + } + else{ + ST(0) = &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 + PPCODE: + { + time_t timep; + if( rpcb_gettime( host, &timep ) ) + PUSHs(sv_2mortal(newSVnv(timep))); + else{ + /* Nothing pushed on stack, so an empty */ + /* list is implicitly returned. */ + } + } + +=head2 The CLEANUP: Keyword + +This keyword can be used when an XSUB requires special cleanup procedures +before it terminates. When the CLEANUP: keyword is used it must follow +any CODE:, PPCODE:, or OUTPUT: blocks which are present in the XSUB. The +code specified for the cleanup block will be added as the last statements +in the XSUB. + +=head2 The BOOT: Keyword + +The BOOT: keyword is used to add code to the extension's bootstrap +function. The bootstrap function is generated by the B<xsubpp> compiler and +normally holds the statements necessary to register any XSUBs with Perl. +With the BOOT: keyword the programmer can tell the compiler to add extra +statements to the bootstrap function. + +This keyword may be used any time after the first MODULE keyword and should +appear on a line by itself. The first blank line after the keyword will +terminate the code block. + + BOOT: + # The following message will be printed when the + # bootstrap function executes. + printf("Hello from the bootstrap!\n"); + +=head2 Inserting Comments and C Preprocessor Directives + +Comments and C preprocessor directives are allowed within +CODE:, PPCODE:, BOOT:, and CLEANUP: blocks. The compiler +will pass the preprocessor directives through untouched and +will remove the commented lines. Comments can be added to +XSUBs by placing a C<#> at the beginning of the line. Care +should be taken to avoid making the comment look like a C +preprocessor directive, lest it be interpreted as such. + +=head2 Using XS With C++ + +If a function is defined as a C++ method then it will assume +its first argument is an object pointer. The object pointer +will be stored in a variable called THIS. The object should +have been created by C++ with the new() function and should +be blessed by Perl with the sv_setptrobj() macro. The +blessing of the object by Perl can be handled by the +T_PTROBJ typemap. + +If the method is defined as static it will call the C++ +function using the class::method() syntax. If the method is not static +the function will be called using the THIS->method() syntax. + +=head2 Perl Variables + +The following demonstrates how the Perl variable $host can +be accessed from an XSUB. The function B<perl_get_sv()> is +used to obtain a pointer to the variable, known as an B<SV> +(Scalar Variable) internally. The package name C<RPC> will be +added to the name of the variable so perl_get_sv() will know +in which package $host can be found. If the package name is +not supplied then perl_get_sv() will search package C<main> for +the variable. The macro B<SvPVX()> is then used to dereference +the SV to obtain a C<char*> pointer to its contents. + + void + rpcb_gettime() + PPCODE: + { + char *host; + SV *hostsv; + time_t timep; + + hostsv = perl_get_sv( "RPC::host", FALSE ); + if( hostsv != NULL ){ + host = SvPVX( hostsv ); + if( rpcb_gettime( host, &timep ) ) + PUSHs(sv_2mortal(newSVnv(timep))); + } + } + +This Perl code can be used to call that XSUB. + + $RPC::host = "localhost"; + $timep = rpcb_gettime(); + +In the above example the SV contained a C C<char*> but a Perl +scalar variable may also contain numbers and references. If +the SV is expected to have a C C<int> then the macro B<SvIVX()> +should be used to dereference the SV. When the SV contains +a C double then B<SvNVX()> should be used. + +The macro B<SvRV()> can be used to dereference an SV when it is a Perl +reference. The result will be another SV which points to the actual Perl +variable. This can then be dereferenced with SvPVX(), SvNVX(), or +SvIVX(). The following XSUB will use SvRV(). + + void rpcb_gettime() + PPCODE: + { + char *host; + SV *rv; + SV *hostsv; + time_t timep; + + rv = perl_get_sv( "RPC::host", FALSE ); + if( rv != NULL ){ + hostsv = SvRV( rv ); + host = SvPVX( hostsv ); + if( rpcb_gettime( host, &timep ) ) + PUSHs(sv_2mortal(newSVnv(timep))); + } + } + +This Perl code will create a variable $RPC::host which is a +reference to $MY::host. The variable $MY::host contains the +hostname which will be used. + + $MY::host = "localhost"; + $RPC::host = \$MY::host; + $timep = rpcb_gettime(); + +The second argument to perl_get_sv() will normally be B<FALSE> +as shown in the above examples. An argument of B<TRUE> will +cause variables to be created if they do not already exist. +One should not use TRUE unless steps are taken to deal with +a possibly empty SV. + +XSUBs may use B<perl_get_av()>, B<perl_get_hv()>, and B<perl_get_cv()> to +access Perl arrays, hashes, and code values. + +=head2 Interface Stategy + +When designing an interface between Perl and a C library a straight +translation from C to XS is often sufficient. The interface will often be +very C-like and occasionally nonintuitive, especially when the C function +modifies one of its parameters. In cases where the programmer wishes to +create a more Perl-like interface the following strategy may help to +identify the more critical parts of the interface. + +Identify the C functions which modify their parameters. The XSUBs for +these functions may be able to return lists to Perl, or may be +candidates to return undef or an empty list in case of failure. + +Identify which values are used only by the C and XSUB functions +themselves. If Perl does not need to access the contents of the value +then it may not be necessary to provide a translation for that value +from C to Perl. + +Identify the pointers in the C function parameter lists and return +values. Some pointers can be handled in XS with the & unary operator on +the variable name while others will require the use of the * operator on +the type name. In general it is easier to work with the & operator. + +Identify the structures used by the C functions. In many +cases it may be helpful to use the T_PTROBJ typemap for +these structures so they can be manipulated by Perl as +blessed objects. + +=head2 The Perl Module + +The Perl module is the link between the extension library, +which was generated from XS code, and the Perl interpreter. +The module is used to tell Perl what the extension library +contains. The name and package of the module should match +the name of the library. + +The following is a Perl module for an extension containing +some ONC+ RPC bind library functions. + + package RPC; + + require Exporter; + require DynaLoader; + @ISA = qw(Exporter DynaLoader); + @EXPORT = qw( rpcb_gettime rpcb_getmaps rpcb_getaddr + rpcb_rmtcall rpcb_set rpcb_unset ); + + bootstrap RPC; + 1; + +The RPC extension contains the functions found in the +@EXPORT list. By using the C<Exporter> module the RPC module +can make these function names visible to the rest of the +Perl program. The C<DynaLoader> module will allow the RPC +module to bootstrap the extension library. To load this +extension and make the functions available, the following +Perl statement should be used. + + use RPC; + +For more information about the DynaLoader consult its documentation in the +ext/DynaLoader directory in the Perl source. + +=head2 Perl Objects And C Structures + +When dealing with C structures one should select either +B<T_PTROBJ> or B<T_PTRREF> for the XS type. Both types are +designed to handle pointers to complex objects. The +T_PTRREF type will allow the Perl object to be unblessed +while the T_PTROBJ type requires that the object be blessed. +By using T_PTROBJ one can achieve a form of type-checking +since the XSUB will attempt to verify that the Perl object +is of the expected type. + +The following XS code shows the getnetconfigent() function which is used +with ONC TIRPC. The getnetconfigent() function will return a pointer to a +C structure and has the C prototype shown below. The example will +demonstrate how the C pointer will become a Perl reference. Perl will +consider this reference to be a pointer to a blessed object and will +attempt to call a destructor for the object. A destructor will be +provided in the XS source to free the memory used by getnetconfigent(). +Destructors in XS can be created by specifying an XSUB function whose name +ends with the word B<DESTROY>. XS destructors can be used to free memory +which may have been malloc'd by another XSUB. + + struct netconfig *getnetconfigent(const char *netid); + +A C<typedef> will be created for C<struct netconfig>. The Perl +object will be blessed in a class matching the name of the C +type, with the tag C<Ptr> appended, and the name should not +have embedded spaces if it will be a Perl package name. The +destructor will be placed in a class corresponding to the +class of the object and the PREFIX keyword will be used to +trim the name to the word DESTROY as Perl will expect. + + typedef struct netconfig Netconfig; + + MODULE = RPC PACKAGE = RPC + + Netconfig * + getnetconfigent(netid) + char * netid + + MODULE = RPC PACKAGE = NetconfigPtr PREFIX = rpcb_ + + void + rpcb_DESTROY(netconf) + Netconfig * netconf + CODE: + printf("Now in NetconfigPtr::DESTROY\n"); + free( netconf ); + +This example requires the following typemap entry. Consult the typemap +section for more information about adding new typemaps for an extension. + + TYPEMAP + Netconfig * T_PTROBJ + +This example will be used with the following Perl statements. + + use RPC; + $netconf = getnetconfigent("udp"); + +When Perl destroys the object referenced by $netconf it will send the +object to the supplied XSUB DESTROY function. Perl cannot determine, and +does not care, that this object is a C struct and not a Perl object. In +this sense, there is no difference between the object created by the +getnetconfigent() XSUB and an object created by a normal Perl subroutine. + +=head2 C Headers and Perl + +The B<h2xs> compiler is designed to convert C header files in +/usr/include into Perl extensions. This compiler will +create a directory under the C<ext> directory of the Perl +source and will populate it with a Makefile, a Perl Module, +an XS source file, and a MANIFEST file. + +The following command will create an extension called C<Rusers> +from the <rpcsvc/rusers.h> header. + + h2xs rpcsvc/rusers + +When the Rusers extension has been compiled and installed +Perl can use it to retrieve any C<#define> statements which +were in the C header. + + use Rusers; + print "RPC program number for rusers service: "; + print &RUSERSPROG, "\n"; + +=head2 Creating A New Extension + +The B<h2xs> compiler can generate template source files and +Makefiles. These templates offer a suitable starting point +for most extensions. The following example demonstrates how +one might use B<h2xs> to create an extension containing the RPC +functions in this document. + +The extension will not use autoloaded functions and will not define +constants, so the B<-A> option will be given to B<h2xs>. When run from the +Perl source directory, the B<h2xs> compiler will create the directory +ext/RPC and will populate it with files called RPC.xs, RPC.pm, Makefile.PL, +and MANIFEST. The XS code for the RPC functions should be added to the +RPC.xs file. The @EXPORT list in RPC.pm should be updated to include the +functions from RPC.xs. + + h2xs -An RPC + +To compile the extension for dynamic loading the following +command should be executed from the ext/RPC directory. + + make dynamic + +If the extension will be statically linked into the Perl +binary then the makefile (use C<makefile>, not C<Makefile>) in the +Perl source directory should be edited to add C<ext/RPC/RPC.a> +to the C<static_ext> variable. Before making this change Perl +should have already been built. After the makefile has been +updated the following command should be executed from the +Perl source directory. + + make + +Perl's B<Configure> script can also be used to add extensions. The extension +should be placed in the C<ext> directory under the Perl source before Perl +has been built and prior to running Configure. When Configure is run it +will find the extension along with the other extensions in the C<ext> +directory and will add it to the list of extensions to be built. When make +is run the extension will be built along with the other extensions. + +Configure recognizes extensions if they have an XS source +file which matches the name of the extension directory. If +the extension directory includes a MANIFEST file Configure +will search that file for any B<.SH> files and extract them +after it extracts all the other .SH files listed in the main +MANIFEST. The main Perl Makefile will then run B<make> in the +extension's directory if it finds an XS file matching the +name of the extension's directory. + +=head2 The Typemap + +The typemap is a collection of code fragments which are used by the B<xsubpp> +compiler to map C function parameters and values to Perl values. The +typemap file may consist of three sections labeled C<TYPEMAP>, C<INPUT>, and +C<OUTPUT>. 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. +Each of the sections of the typemap must be preceded by one of the TYPEMAP, +INPUT, or OUTPUT keywords. + +The default typemap in the C<ext> directory of the Perl source contains many +useful types which can be used by Perl extensions. Some extensions define +additional typemaps which they keep in their own directory. These +additional typemaps may reference INPUT and OUTPUT maps in the main +typemap. The B<xsubpp> compiler will allow the extension's own typemap to +override any mappings which are in the default typemap. + +Most extensions which require a custom typemap will need only the TYPEMAP +section of the typemap file. The custom typemap used in the +getnetconfigent() example shown earlier demonstrates what may be the typical +use of extension typemaps. That typemap is used to equate a C structure +with the T_PTROBJ typemap. The typemap used by getnetconfigent() is shown +here. Note that the C type is separated from the XS type with a tab and +that the C unary operator C<*> is considered to be a part of the C type name. + + TYPEMAP + Netconfig *<tab>T_PTROBJ + +=head1 EXAMPLES + +File C<RPC.xs>: Interface to some ONC+ RPC bind library functions. + + #include "EXTERN.h" + #include "perl.h" + #include "XSUB.h" + + #include <rpc/rpc.h> + + typedef struct netconfig Netconfig; + + MODULE = RPC PACKAGE = RPC + + void + rpcb_gettime(host="localhost") + char * host + CODE: + { + time_t timep; + ST(0) = sv_newmortal(); + if( rpcb_gettime( host, &timep ) ) + sv_setnv( ST(0), (double)timep ); + } + + Netconfig * + getnetconfigent(netid="udp") + char * netid + + MODULE = RPC PACKAGE = NetconfigPtr PREFIX = rpcb_ + + void + rpcb_DESTROY(netconf) + Netconfig * netconf + CODE: + printf("NetconfigPtr::DESTROY\n"); + free( netconf ); + +File C<typemap>: Custom typemap for RPC.xs. + + TYPEMAP + Netconfig * T_PTROBJ + +File C<RPC.pm>: Perl module for the RPC extension. + + package RPC; + + require Exporter; + require DynaLoader; + @ISA = qw(Exporter DynaLoader); + @EXPORT = qw(rpcb_gettime getnetconfigent); + + bootstrap RPC; + 1; + +File C<rpctest.pl>: Perl test program for the RPC extension. + + use RPC; + + $netconf = getnetconfigent(); + $a = rpcb_gettime(); + print "time = $a\n"; + print "netconf = $netconf\n"; + + $netconf = getnetconfigent("tcp"); + $a = rpcb_gettime("poplar"); + print "time = $a\n"; + print "netconf = $netconf\n"; + + +=head1 AUTHOR + +Dean Roehrich <roehrich@cray.com> +September 27, 1994 |