home *** CD-ROM | disk | FTP | other *** search
- =head1 NAME
-
- perlXStut - Tutorial for 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> 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 to ease the
- reader slowly into building extensions.
-
- =head2 VERSION CAVEAT
-
- This tutorial tries hard to keep up with the latest development versions
- of Perl. This often means that it is sometimes in advance of the latest
- released version of Perl, and that certain features described here might
- not work on earlier versions. This section will keep track of when various
- features were added to Perl 5.
-
- =over 4
-
- =item *
-
- In versions of Perl 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 Perl 5.002 prior to version beta 3, the line in the .xs file
- about "PROTOTYPES: DISABLE" will cause a compiler error. Simply remove that
- line from the file.
-
- =item *
-
- In versions of Perl 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
-
- =head2 DYNAMIC VERSUS STATIC
-
- It is commonly thought that if a system does not have the capability to
- load a library dynamically, you cannot build XSUBs. This is incorrect.
- You I<can> build them, but you must link the XSUB's 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 "make" with no arguments is executed, run the command
- "make perl" instead.
-
- If you have generated such a statically-linked executable by choice, then
- instead of saying "make test", you should say "make test_static". On systems
- that cannot build dynamically-loadable libraries at all, simply saying "make
- test" is sufficient.
-
- =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 created.
-
- 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;
-
- require Exporter;
- require DynaLoader;
-
- @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.
- @EXPORT = qw(
-
- );
- $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!
-
- And the Mytest.xs file should look something like this:
-
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "EXTERN.h"
- #include "perl.h"
- #include "XSUB.h"
- #ifdef __cplusplus
- }
- #endif
-
- PROTOTYPES: DISABLE
-
- 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");
-
- Now we'll run "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 shortened for clarity):
-
- % make
- umask 0 && cp Mytest.pm ./blib/Mytest.pm
- perl xsubpp -typemap typemap Mytest.xs >Mytest.tc && mv Mytest.tc Mytest.c
- 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
-
- Now, although there is already a test.pl template ready for us, for this
- example only, we'll create a special test script. Create a file called hello
- that looks like this:
-
- #! /opt/perl5/bin/perl
-
- use ExtUtils::testlib;
-
- use Mytest;
-
- Mytest::hello();
-
- Now we run the script and we should see the following output:
-
- % perl hello
- Hello, world!
- %
-
- =head2 EXAMPLE 2
-
- Now let's add to our extension a subroutine that will take a single argument
- and return 1 if the argument is even, 0 if the argument 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 "int input" line,
- but it is useful for improving readability. The semi-colon at the end of
- that line is also optional.
-
- Any white space may be between the "int" and "input". It is also okay for
- the four lines starting at the "CODE:" line to not be indented. However,
- for readability purposes, it is suggested that you indent them 8 spaces
- (or one normal tab stop).
-
- Now rerun 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.
-
- 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 "make test". You
- should see output that looks something like this:
-
- % make test
- PERL_DL_NONLAZY=1 /opt/perl5.002b2/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 files E<lt>extensionE<gt>.pm and E<lt>extensionE<gt>.xs 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 and invoking the Makefile created a directory 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 "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 "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 "make test" to run your test script
- is that if you are testing an upgrade to an already-existing version, using
- "make test" insures that you use 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 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
- @INC array.
-
- In our case, Mytest.pm tells perl that it will need the Exporter and Dynamic
- Loader extensions. It then sets the @ISA and @EXPORT arrays and the $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 that are set in the .pm file are very important. The @ISA
- array contains a list of other packages in which to search for methods (or
- subroutines) that do not exist in the current package. The @EXPORT array
- tells Perl which of the extension's routines should be placed into the
- calling package's namespace.
-
- It's important to select what to export carefully. Do NOT export method names
- and do NOT export anything else 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 then you can export
- any of the functions via another array, called @EXPORT_OK.
-
- See L<perlmod> for more information.
-
- The $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 "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", and
- ensure all your test files end with the suffix ".t". The Makefile will
- properly run all these test files.
-
-
- =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 out
- "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 "make test" should now print out that all nine tests are okay.
-
- You might be wondering if you can round a constant. To see what happens, add
- the following line to test.pl temporarily:
-
- &Mytest::round(3);
-
- Run "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?
-
- Two things are new here. First, we've made some changes to Makefile.PL.
- In this case, we've specified an extra library to link in, the math library
- libm. We'll talk later about how to write XSUBs that can call every routine
- in a library.
-
- Second, the value of the function is being passed back not as the function's
- return value, but through the same variable that was passed into the function.
-
- =head2 INPUT AND OUTPUT PARAMETERS
-
- You specify the parameters that will be passed into the XSUB just after you
- declare the function return value and name. Each parameter line starts with
- optional white space, and may have an optional terminating semicolon.
-
- The list of output parameters occurs 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, the value we wanted returned was
- contained in the same variable we passed in, so we listed it (and not RETVAL)
- in the OUTPUT: section.
-
- =head2 THE XSUBPP COMPILER
-
- The compiler xsubpp takes the XS code in the .xs file and converts 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 xsubpp compiler 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 part attempts to map various C data types to a coded flag, which
- has some correspondence with the various Perl types. The second part contains
- C code which xsubpp uses for input parameters. The third part contains C
- code which xsubpp uses for output parameters. We'll talk more about the
- C code later.
-
- Let's now take a look at a portion of the .c file created for our extension.
-
- 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 marked 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
-
- In general, it's not a good idea to write extensions that modify their input
- parameters, as in Example 3. However, to accommodate better calling
- pre-existing C routines, which often do modify their input parameters,
- this behavior is tolerated. The next example will show how to do this.
-
- =head2 EXAMPLE 4
-
- In this example, we'll now begin to write XSUBs that will interact with
- predefined 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 testlib 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(a, b, c)
- 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
-
- static :: libmylib$(LIB_EXT)
-
- libmylib$(LIB_EXT): $(O_FILES)
- $(AR) cr libmylib$(LIB_EXT) $(O_FILES)
- $(RANLIB) libmylib$(LIB_EXT)
-
- ';
- }
-
- 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 following key-value
- pair to the WriteMakefile call:
-
- 'MYEXTLIB' => 'mylib/libmylib$(LIB_EXT)',
-
- and a new replacement subroutine too:
-
- sub MY::postamble {
- '
- $(MYEXTLIB): mylib/Makefile
- cd mylib && $(MAKE) $(PASTHRU)
- ';
- }
-
- (Note: Most makes will require that there be a tab character that indents
- the line C<cd mylib && $(MAKE) $(PASTHRU)>, similarly for the Makefile in the
- subdirectory.)
-
- 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 lines setting @EXPORT to @EXPORT_OK (there are two: one in the line
- beginning "use vars" and one setting the array itself). 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 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 see 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 often useful not to check
- for equality, but rather the difference being below a certain epsilon factor,
- 0.01 in this case)
-
- Run "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 declaration with the full path to
- the mylib.h header file.
-
- =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 available to the Perl script (in this case, by calling
- C<&main::TESTVAL>). There's also some XS code to allow calls to the
- C<constant> routine.
-
- =item *
-
- The .pm file has exported the name TESTVAL in the @EXPORT array. This
- could lead to name clashes. A good rule of thumb is that if the #define
- is going to be used by only the C routines themselves, and not by the user,
- they should be removed from the @EXPORT array. Alternately, if you don't
- mind using the "fully qualified name" of a variable, you could remove most
- or all of the items in the @EXPORT array.
-
- =item *
-
- If our include file contained #include directives, these would not be
- processed at all by h2xs. There is no good solution to this right now.
-
- =back
-
- We've also told Perl about the library that we built in the mylib
- subdirectory. That required the addition of only the 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
- specified simply that the library to be created here was a static
- archive (as opposed to a dynamically loadable library) and provided the
- commands to build it.
-
- =head2 SPECIFYING ARGUMENTS TO XSUBPP
-
- 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
- xsubpp compiler.
-
- When you specify arguments in the .xs file, you are really passing three
- pieces of information for each one 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 exact way in
- which the argument should be used in the call to the library function
- from this XSUB. This would mean whether or not to place a "&" before
- the argument or not, meaning the argument expects to be passed the address
- of the specified data type.
-
- There is a difference between the two arguments in this hypothetical function:
-
- int
- foo(a,b)
- char &a
- char * b
-
- The first 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 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 xsubpp generates would look like this:
-
- foo(&a, b);
-
- Xsubpp will identically parse the following function argument lists:
-
- 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
- complete example 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. The "ST" is actually a macro that points to the n'th argument
- on the argument stack. ST(0) is thus 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 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.
-
- =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 loaded only when called depends on where in the .pm file the subroutine
- definition is placed.
-
- =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 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.
-
- =head2 SEE ALSO
-
- For more information, consult L<perlguts>, L<perlxs>, L<perlmod>,
- and L<perlpod>.
-
- =head2 Author
-
- Jeff Okamoto <F<okamoto@corp.hp.com>>
-
- Reviewed and assisted by Dean Roehrich, Ilya Zakharevich, Andreas Koenig,
- and Tim Bunce.
-
- =head2 Last Changed
-
- 1996/7/10
-