diff options
Diffstat (limited to 'contrib/perl5/pod/perlxstut.pod')
-rw-r--r-- | contrib/perl5/pod/perlxstut.pod | 1263 |
1 files changed, 0 insertions, 1263 deletions
diff --git a/contrib/perl5/pod/perlxstut.pod b/contrib/perl5/pod/perlxstut.pod deleted file mode 100644 index f06e166..0000000 --- a/contrib/perl5/pod/perlxstut.pod +++ /dev/null @@ -1,1263 +0,0 @@ -=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<perlguts>, -L<perlapi> and L<perlxs>. - -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<make>. 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<perl -V:make> 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<README> file, but nowadays -installation of extensions may be performed automatically, guided by F<CPAN.pm> -module or other tools. - -In MakeMaker-based installations, F<Makefile.PL> provides the earliest -opportunity to perform version checks. One can put something like this -in F<Makefile.PL> for this purpose: - - eval { require 5.007 } - or die <<EOD; - ############ - ### This module uses frobnication framework which is not available before - ### version 5.007 of Perl. Upgrade your Perl before installing Kara::Mba. - ############ - EOD - -=head2 Dynamic Loading versus Static Loading - -It is commonly thought that if a system does not have the capability to -dynamically load a library, you cannot build XSUBs. This is incorrect. -You I<can> 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<make>" with no arguments is executed, run the command -"C<make perl>" instead. - -If you have generated such a statically-linked executable by choice, then -instead of saying "C<make test>", you should say "C<make test_static>". -On systems that cannot build dynamically-loadable libraries at all, simply -saying "C<make test>" is sufficient. - -=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<h2xs -A -n Mytest>". This creates a directory named Mytest, -possibly under ext/ if that directory exists in the current working -directory. Several files will be created in the Mytest dir, including -MANIFEST, Makefile.PL, Mytest.pm, Mytest.xs, test.pl, 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 strict; - use warnings; - - require Exporter; - require DynaLoader; - - our @ISA = qw(Exporter DynaLoader); - # Items to export into callers namespace by default. Note: do not export - # names by default without a very good reason. Use EXPORT_OK instead. - # Do not simply export all your public functions/methods/constants. - our @EXPORT = qw( - - ); - our $VERSION = '0.01'; - - bootstrap Mytest $VERSION; - - # Preloaded methods go here. - - # Autoload methods go after __END__, and are processed by the autosplit program. - - 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: - - #include "EXTERN.h" - #include "perl.h" - #include "XSUB.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<perl Makefile.PL>". 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 - umask 0 && cp Mytest.pm ./blib/Mytest.pm - perl xsubpp -typemap typemap Mytest.xs >Mytest.tc && mv Mytest.tc Mytest.c - Please specify prototyping behavior for Mytest.xs (see perlxs manual) - cc -c Mytest.c - Running Mkbootstrap for Mytest () - chmod 644 Mytest.bs - LD_RUN_PATH="" ld -o ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl -b Mytest.o - chmod 755 ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl - cp Mytest.bs ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs - chmod 644 ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs - Manifying ./blib/man3/Mytest.3 - % - -You can safely ignore the line about "prototyping behavior" - it is -explained in the section "The PROTOTYPES: Keyword" in L<perlxs>. - -If you are on a Win32 system, and the build process fails with linker -errors for functions in the C library, check if your Perl is configured -to use PerlCRT (running B<perl -V:libc> should show you if this is the -case). If Perl is configured to use PerlCRT, you have to make sure -PerlCRT.lib is copied to the same location that msvcrt.lib lives in, -so that the compiler can find it on its own. msvcrt.lib is usually -found in the Visual C compiler's lib directory (e.g. C:/DevStudio/VC/lib). - -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<chmod -x hello>), 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 0 if the number is even or 1 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 white space at the start of the "C<int input>" -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 white space -may be placed between the "C<int>" and "C<input>". - -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 test.pl. 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. Change the print -statement in the BEGIN block to print "1..4", and add the following code -to the end of the file: - - print &Mytest::is_even(0) == 1 ? "ok 2" : "not ok 2", "\n"; - print &Mytest::is_even(1) == 0 ? "ok 3" : "not ok 3", "\n"; - print &Mytest::is_even(2) == 1 ? "ok 4" : "not ok 4", "\n"; - -We will be calling the test script through the command "C<make test>". You -should see output that looks something like this: - - % make test - PERL_DL_NONLAZY=1 /opt/perl5.004/bin/perl (lots of -I arguments) test.pl - 1..4 - ok 1 - ok 2 - ok 3 - ok 4 - % - -=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<make> 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<make test>" 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<very> important that -while you are still testing extensions that you use "C<make test>". 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<make test>" to run your test -script is that if you are testing an upgrade to an already-existing version, -using "C<make test>" insures that you will test your new extension, not the -already-existing version. - -When Perl sees a C<use extension;>, it searches for a file with the same name -as the C<use>'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<not> -export method or variable names I<by default> 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<perlmod> 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 overemphasized. 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<make test>", you ensure that your test.pl script runs and uses -the correct version of your extension. If you have many test cases, you -might want to copy Perl's test style. Create a directory named "t" in the -extension's directory and append the suffix ".t" to the names of your test -files. When you run "C<make test>", 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<argument> 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 BEGIN block to print -"1..9" and add the following to test.pl: - - $i = -1.5; &Mytest::round($i); print $i == -2.0 ? "ok 5" : "not ok 5", "\n"; - $i = -1.1; &Mytest::round($i); print $i == -1.0 ? "ok 6" : "not ok 6", "\n"; - $i = 0.0; &Mytest::round($i); print $i == 0.0 ? "ok 7" : "not ok 7", "\n"; - $i = 0.5; &Mytest::round($i); print $i == 1.0 ? "ok 8" : "not ok 8", "\n"; - $i = 1.2; &Mytest::round($i); print $i == 1.0 ? "ok 9" : "not ok 9", "\n"; - -Running "C<make test>" 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 test.pl: - - &Mytest::round(3); - -Run "C<make test>" 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 white space, and may have an optional terminating -semicolon. - -The list of output parameters occurs at the very end of the function, just -before 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<xsubpp> 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<xsubpp> 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). This file 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<xsubpp> uses to handle input parameters. The third section contains -C code which B<xsubpp> 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) - croak("Usage: Mytest::round(arg)"); - { - 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 */ - } - XSRETURN(1); - } - -Notice the two lines commented with "XXXXX". If you check the first section -of the typemap file, you'll see that doubles are of type T_DOUBLE. In the -INPUT section, 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<perlguts>; 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 <stdlib.h> - #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$(LIBEEXT)'}, - ); - - - 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 file because the default Perl doesn't -currently support the const char * type. Create a file called typemap in -the Mytest2 directory and place the following in it: - - const char * T_PV - -Now run perl on the top-level Makefile.PL. Notice that it also created a -Makefile in the mylib directory. Run make and watch that it does cd into -the mylib directory and run make in there as well. - -Now edit the test.pl script and change the BEGIN block to print "1..4", -and add the following lines to the end of the script: - - print &Mytest2::foo(1, 2, "Hello, world!") == 7 ? "ok 2\n" : "not ok 2\n"; - print &Mytest2::foo(1, 2, "0.0") == 7 ? "ok 3\n" : "not ok 3\n"; - print abs(&Mytest2::foo(0, 0, "-3.4") - 0.6) <= 0.01 ? "ok 4\n" : "not ok 4\n"; - -(When dealing with floating-point comparisons, it is best to not check for -equality, but rather that the difference between the expected and actual -result is below a certain amount (called epsilon) which is 0.01 in this case) - -Run "C<make test>" and all should be well. - -=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<constant> routine is to make the values that are #define'd in the -header file accessible by the Perl script (by calling either C<TESTVAL> or -C<&Mytest2::TESTVAL>). There's also some XS code to allow calls to the -C<constant> routine. - -=item * - -The .pm file originally exported the name C<TESTVAL> 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<MYEXTLIB> 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<perlpod>) 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<xsubpp> 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<constant>. This name appears -twice in the generated .xs file: once in the first part, as a static C -function, the 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<code> for what is done -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<xsubpp> -compiler is smart enough to figure out the C<CODE:> section from the first -two lines of the description of XSUB. What about C<OUTPUT:> section? In -fact, that is absolutely the same! The C<OUTPUT:> section can be removed -as well, I<as far as C<CODE:> section or C<PPCODE:> section> is not -specified: B<xsubpp> 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<int -is_even(int input)>. As we saw in L<Anatomy of .xs file>, 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<xsubpp> 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<xsubpp> 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<cp> -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<xsubpp> 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<value> of b would be passed into the function foo. The -actual call to the function foo that B<xsubpp> generates would look like this: - - foo(&a, b); - -B<xsubpp> 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<xsubpp> -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<perlxs> for details. - -XSUBs are also allowed to avoid automatic conversion of Perl function arguments -to C function arguments. See L<perlxs> for details. Some people prefer -manual conversion by inspecting C<ST(i)> 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<AutoLoader> 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 man page format, -then placed in the blib directory. It will be copied to Perl's man -page 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<perlpod> 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))); - XPUSHs(sv_2mortal(newSVnv(buf.f_fsid[0]))); - XPUSHs(sv_2mortal(newSVnv(buf.f_fsid[1]))); - } 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 <sys/vfs.h> - -Also add the following code segment to test.pl while incrementing the "1..9" -string in the BEGIN block to "1..11": - - @a = &Mytest::statfs("/blech"); - print ((scalar(@a) == 1 && $a[0] == 2) ? "ok 10\n" : "not ok 10\n"); - @a = &Mytest::statfs("/"); - print scalar(@a) == 9 ? "ok 11\n" : "not ok 11\n"; - -=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<PPCODE:> 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 9-element array is returned. Since only one argument is passed into -this function, we need room on the stack to hold the 9 values which may be -returned. - -We do this by using the PPCODE: directive, rather than the CODE: directive. -This tells B<xsubpp> 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<XPUSHs> macros, but C<PUSHs> macros, and would -pre-extend the stack before pushing the return values: - - EXTEND(SP, 9); - -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<PUSHs> I<without> extending -the stack: the Perl function reference comes to an XSUB on the stack, thus -the stack is I<always> 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; - I32 numpaths = 0; - int i, n; - struct statfs buf; - - if ((!SvROK(paths)) - || (SvTYPE(SvRV(paths)) != SVt_PVAV) - || ((numpaths = av_len((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((SV *)rh)); - } - RETVAL = newRV((SV *)results); - OUTPUT: - RETVAL - -And add the following code to test.pl, while incrementing the "1..11" -string in the BEGIN block to "1..13": - - $results = Mytest::multi_statfs([ '/', '/blech' ]); - print ((ref $results->[0]) ? "ok 12\n" : "not ok 12\n"); - print ((! ref $results->[1]) ? "ok 13\n" : "not ok 13\n"); - -=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<PPCODE:> directive - instead, we use C<CODE:> -and C<OUTPUT:> directives. - -=item * - -When dealing with references, it is important to handle them with caution. -The C<INIT:> block first checks that -C<SvROK> returns true, which indicates that paths is a valid reference. It -then verifies that the object referenced by paths is an array, using C<SvRV> -to dereference paths, and C<SvTYPE> to discover its type. As an added test, -it checks that the array referenced by paths is non-empty, using the C<av_len> -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<av_len> returns the highest -index in an AV*, much like $#array; C<av_fetch> fetches a single scalar value -from an array, given its index; C<av_push> 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<hv_store>. 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<perlguts> and L<perlapi> -for details. - -=item * - -To create a reference, we use the C<newRV> 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<SvRV> function always returns an SV*, which may -need to be be cast to the appropriate type if it is something other than a -scalar (check with C<SvTYPE>). - -=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 (Coming Soon) - -Getting fd's from filehandles - -=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<perlguts>, L<perlapi>, L<perlxs>, L<perlmod>, -and L<perlpod>. - -=head1 Author - -Jeff Okamoto <F<okamoto@corp.hp.com>> - -Reviewed and assisted by Dean Roehrich, Ilya Zakharevich, Andreas Koenig, -and Tim Bunce. - -=head2 Last Changed - -1999/11/30 |