📄 ch21_03.htm
字号:
<html><head><title>Extending Perl (Using C from Perl) (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Extending Perl (Using C from Perl)"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch21_02.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="ch21_01.htm">Chapter 21: Internals and Externals</a></td><td align="right" valign="top" width="172"><a href="ch21_04.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">21.3. Extending Perl (Using C from Perl)</h2><a name="INDEX-3694"></a><a name="INDEX-3695"></a><a name="INDEX-3696"></a><a name="INDEX-3697"></a><p><a name="INDEX-3698"></a><a name="INDEX-3699"></a><a name="INDEX-3700"></a><a name="INDEX-3701"></a>If you want to use C source code (or a C library) from Perl, you needto create a library that can be either dynamically loaded or staticallylinked into your <em class="emphasis">perl</em> executable. (Dynamic loading is usuallypreferred, to minimize the number of different <em class="emphasis">perl</em> executablessitting around being different.) You create that library by creating an<em class="emphasis">XS</em> file (ending in <em class="emphasis">.xs</em>) containing a series of wrappersubroutines. The wrapper subroutines are not Perl subroutines,however; they are in the XS language, and we call such a subroutine an<em class="emphasis">XSUB</em>, for "eXternal SUBroutine". An XSUB can wrap a C function from anexternal library, a C function elsewhere in the XS file, or naked Ccode in the XSUB itself. You then use the <em class="emphasis">xsubpp</em> utility bundledwith Perl to take the XS file and translate it into C code that can becompiled into a library that Perl will understand.</p><p>Assuming your operating system supports dynamic linking, the endresult will be a Perl module that behaves like any other modulewritten in 100% pure Perl, but runs compiled C code under the hood.It does this by pulling arguments from Perl's argument stack,converting the Perl values to the formats expected by a particular Cfunction (specified through an XSUB declaration), calling the Cfunction, and finally transferring the return values of the C functionback to Perl. These return values may be passed back to Perl eitherby putting them on the Perl stack or by modifying the argumentssupplied from the Perl side. (If your system doesn't supportdynamic linking, you have another hoop to jump through, and we'lldiscuss that in the next section.)</p><p>The previous description is a somewhat simplified view of what reallyhappens. Since Perl allows more flexible calling conventions than C,XSUBs can do much more in practice, such as checking input parametersfor validity, throwing exceptions, returning <tt class="literal">undef</tt>or an empty list, calling different C functions based on numbers andtypes of the arguments, or providing an object-oriented interface.Again, see the <em class="emphasis">perlxs</em> and<em class="emphasis">perlxstut</em> manpages.</p><h3 class="sect2">21.3.1. XS and XSUBs</h3><a name="INDEX-3702"></a><a name="INDEX-3703"></a><a name="INDEX-3704"></a><a name="INDEX-3705"></a><a name="INDEX-3706"></a><a name="INDEX-3707"></a><a name="INDEX-3708"></a><p>XS is a convenience: there's nothing stopping you from writing gluecode directly in C and linking it into your Perl executable. However,this would be tedious, especially if you need to write glue formultiple C functions, or if you're not familiar with the Perl stackdiscipline and other arcana. XS lets you write a concise descriptionof what should be done by the glue, and the XS compiler <em class="emphasis">xsubpp</em>handles the rest.</p><p><a name="INDEX-3709"></a>For people who don't find XS convenient enough, the SWIG systemautomatically generates simple XSUBs. See <a href="http://www.swig.org">http://www.swig.org</a> formore information.</p><p><a name="INDEX-3710"></a><a name="INDEX-3711"></a><a name="INDEX-3712"></a>The XS language allows you to describe the mapping between a Cfunction and a Perl function. It also allows you to create a Perlfunction that is a wrapper around pure C code that you write yourself.When XS is used merely to map between C and Perl, the XSUB declarationis almost identical to a declaration of a C function. In suchcircumstances, a tool called <em class="emphasis">h2xs</em> (bundled with Perl) is able totranslate an entire C header file into a corresponding XS file thatprovides glue to the C functions and macros.</p><p>The <em class="emphasis">xsubpp</em> tool creates the constructs necessary to let an XSUBmanipulate Perl values and the glue necessary to let Perlcall the XSUB.</p><p>An XS file begins with any C code you want to include, which will oftenbe nothing more than a set of <tt class="literal">#include</tt> directives. After a <tt class="literal">MODULE</tt>keyword, the remainder of the file should be in the XS"language", a combination of XS directives and XSUB definitions. We'llsee an example of an entire XS file soon, but in the meantime here is asimple XSUB definition that allows a Perl program to access a C libraryfunction called <em class="emphasis">sin</em>(3). The XSUB specifies the return type (a doublelength floating-point number), the function name and argument list(with one argument dubbed <tt class="literal">x</tt>), and the type of the argument (another double):<blockquote><pre class="programlisting">doublesin(x) double x</pre></blockquote>More complicated XSUBs will often contain other bits of XS code.Each section of an XSUB starts with a keyword followed by a colon,such as <tt class="literal">INIT:</tt> or <tt class="literal">CLEANUP:</tt>. However, the first two lines of anXSUB always contain the same data: a description of the return typeand the name of the function and its parameters. Whatever immediatelyfollows these is considered to be an <tt class="literal">INPUT:</tt> section unlessexplicitly marked with another keyword. The various keywords are allexplained in the <em class="emphasis">perlxs</em> manpage, which you should read to learn abouteverything you can do with XSUBs.</p><p><a name="INDEX-3713"></a><a name="INDEX-3714"></a>If your system does not have the capability to dynamically loadshared libraries, you can still use XSUBs, but you must statically link theXSUBs with the rest of Perl, creating a new Perl executable (to sitaround and be different). The XSUB build mechanism will check thesystem and build a shared library if possible, or else astatic library. Optionally, it can build a new statically linked executablewith that static library linked in. (But you might want to delay thatto bundle all your new extensions into a single executable sittingaround being the same, as it were.)</p><p>If your system can link libraries dynamically but you still want tobuild a statically linked executable, you can run <tt class="literal">make perl</tt> insteadof <tt class="literal">make</tt> in the following examples. You should then run <tt class="literal">maketest_static</tt> instead of <tt class="literal">make test</tt> to test your extension.</p><p><a name="INDEX-3715"></a>The <em class="emphasis">xsubpp</em> program also needs to know how toconvert from Perl's data types to C's data types. Often it can guess,but with user-defined types you may need to help it out by specifyingthe conversion in a <em class="emphasis">typemap</em> file. The defaultconversions are stored in<em class="replaceable">PATH-TO-PERLLIB</em><em class="emphasis">/ExtUtils/typemap</em>.</p><p>The typemap is split into three sections. The first section, labeled<tt class="literal">TYPEMAP</tt>, tells the compiler which of the code fragments in thefollowing two sections should be used to map between C types and Perlvalues. The second section, <tt class="literal">INPUT</tt>, contains C code specifying howPerl values should be converted to C types. The third section,<tt class="literal">OUTPUT</tt>, contains C code specifying how to translate C types intoPerl values.</p><h3 class="sect2">21.3.2. Creating Extensions</h3><a name="INDEX-3716"></a><a name="INDEX-3717"></a><a name="INDEX-3718"></a><a name="INDEX-3719"></a><a name="INDEX-3720"></a><a name="INDEX-3721"></a><a name="INDEX-3722"></a><p>A proper extension consists of several files: one containing the XS code, plus other supporting files that help Perl figure out what to do with theXS code. You can create all of these files by hand, but it's easierto use the <em class="emphasis">h2xs</em> tool, which creates a skeletal extension thatyou can then flesh out:<blockquote><pre class="programlisting">h2xs -A -n Mytest</pre></blockquote>This creates a directory named <em class="emphasis">Mytest</em>, possibly under <em class="emphasis">ext/</em> if thatdirectory exists in the current directory. Six files will be createdin the <em class="emphasis">Mytest</em> directory: <em class="emphasis">MANIFEST</em>, <em class="emphasis">Makefile.PL</em>, <em class="emphasis">Mytest.pm</em>,<em class="emphasis">Mytest.xs</em>, <em class="emphasis">test.pl</em>, and <em class="emphasis">Changes</em>. We describe the first four below.</p><dl><dt><b><em class="emphasis">MANIFEST</em></b></dt><dd><p><a name="INDEX-"></a>The <em class="emphasis">MANIFEST</em> file contains the names of all the files just created inthe <em class="emphasis">Mytest</em> directory. If you add more files to your extension andintend to distribute it to the wide world, add the filenames here. Thisis tested by some systems to ensure that your distribution iscomplete.</p></dd><dt><b><em class="emphasis">Makefile.PL</em></b></dt><dd><p>This is a Perl program that generates a <em class="emphasis">Makefile</em>(which is then passed to <em class="emphasis">make</em> or an equivalent).<em class="emphasis">Makefile.PL</em> is described further in "CreatingCPAN Modules" in <a href="ch22_01.htm">Chapter 22, "CPAN"</a>.</p></dd><dt><b><em class="emphasis">Mytest.pm</em></b></dt><dd><p>Users will <tt class="literal">use</tt> this module when theywant to load your extension. You're expected to fill in the blanks inthe skeletal module created for you by <em class="emphasis">h2xs</em>:<blockquote><pre class="programlisting">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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -