📄 ch21_03.htm
字号:
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!</pre></blockquote><a name="INDEX-"></a><a name="INDEX-"></a><a name="INDEX-"></a></p><p>Most extension modules will <tt class="literal">require</tt> the <tt class="literal">Exporter</tt> and <tt class="literal">DynaLoader</tt> extensions. After setting <tt class="literal">@ISA</tt> (for inheritance)and <tt class="literal">@EXPORT</tt> (to make functions available to the package using themodule), the initialization code tells Perl to <tt class="literal">bootstrap</tt> the XS code. Perl thendynamically links the shared library into the <em class="emphasis">perl</em> process at run time.</p></dd><dt><b><em class="emphasis">Mytest.xs</em></b></dt><dd><p>The <em class="emphasis">Mytest.xs</em> file contains the XSUBs that tell Perl how to pass datato the compiled C routines. Initially, <em class="emphasis">Mytest.xs</em> will look somethinglike this:<blockquote><pre class="programlisting">#include "EXTERN.h"#include "perl.h"#include "XSUB.h"MODULE = Mytest PACKAGE = Mytest</pre></blockquote>Let's edit the XS file by adding this to the end of the file:<blockquote><pre class="programlisting">voidhello() CODE: printf("Hello, world!\n");</pre></blockquote></p></dd></dl><p></p><p>When you run <tt class="literal">perl Makefile.PL</tt>, the <em class="emphasis">Makefile</em> that <em class="emphasis">make</em> needs willbe created:<blockquote><pre class="programlisting">% <tt class="userinput"><b>perl Makefile.PL</b></tt>Checking if your kit is complete...Looks goodWriting Makefile for Mytest</pre></blockquote>Running <em class="emphasis">make</em> will now produce output that looks something like this(some long lines have been shortened for clarity and some extraneouslines have been deleted):<blockquote><pre class="programlisting">% <tt class="userinput"><b>make</b></tt>umask 0 && cp Mytest.pm ./blib/Mytest.pmperl xsubpp -typemap typemap Mytest.xs >Mytest.tc && mv Mytest.tc Mytest.ccc -c Mytest.cRunning Mkbootstrap for Mytest ()chmod 644 Mytest.bsLD_RUN_PATH="" ld -o ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl -b Mytest.ochmod 755 ./blib/PA-RISC1.1/auto/Mytest/Mytest.slcp Mytest.bs ./blib/PA-RISC1.1/auto/Mytest/Mytest.bschmod 644 ./blib/PA-RISC1.1/auto/Mytest/Mytest.bsManifying ./blib/man3/Mytest.3</pre></blockquote>We assume that the <em class="emphasis">make</em> program that Perl uses to build programs iscalled <em class="emphasis">make</em>. Instead of running <em class="emphasis">make</em> in these examples, you mayhave to substitute whatever <em class="emphasis">make</em> program Perl has been configuredto use. You can find out what that program is with:<blockquote><pre class="programlisting">% <tt class="userinput"><b>perl -V:make</b></tt></pre></blockquote><a name="INDEX-3723"></a></p><p>Running <em class="emphasis">make</em> created a directory called <em class="emphasis">blib</em> (for "buildlibrary") in the current working directory. This directory willcontain the shared library that we will build. Once we're sure weknow what we're doing, we can install it from that directory into itsfinal resting place. Until then, we'll have to explicitly add the<em class="emphasis">blib</em> directory to Perl's <tt class="literal">@INC</tt> array by using the<tt class="literal">ExtUtils::testlib</tt> module. If we now create a file called <em class="emphasis">hello</em>that looks like this:</p><blockquote><pre class="programlisting">use ExtUtils::testlib; # adds blib/* directories to @INCuse Mytest;Mytest::hello();</pre></blockquote><p>we can burrow down from Perl into C:</p><blockquote><pre class="programlisting">% <tt class="userinput"><b>perl hello</b></tt>Hello, world!</pre></blockquote><p>Once your extension is complete and passes all its tests, you caninstall it with <tt class="literal">make install</tt>.</p><p>You will need write permission for your Perl library. (If you don't have permission, you can specify another directory as shown in "Installing CPAN modules" in <a href="ch22_01.htm">Chapter 22, "CPAN"</a>.)</p><a name="INDEX-3724"></a><a name="INDEX-3725"></a><a name="INDEX-3726"></a><h3 class="sect2">21.3.3. XSUB Input and Output</h3><p><a name="INDEX-3727"></a><a name="INDEX-3728"></a><a name="INDEX-3729"></a><a name="INDEX-3730"></a><a name="INDEX-3731"></a><a name="INDEX-3732"></a>Continuing with the previous example, we'll add a second XSUB, whichtakes a single numeric argument as input and returns 0 if the numberis even, or 1 if the number is odd:<blockquote><pre class="programlisting">intis_even(x) int x CODE: RETVAL = (x % 2 == 0); OUTPUT: RETVAL</pre></blockquote>The list of output parameters occurs at the very end of the function,just after the <tt class="literal">OUTPUT:</tt> directive. The use of <tt class="literal">RETVAL</tt> tells Perlthat you wish to send this value back as the return value of the XSUB.Had we wanted the function to modify its input parameter, we wouldhave used <tt class="literal">x</tt> in place of <tt class="literal">RETVAL</tt>.</p><p>We can rebuild our new shared library with the same steps as before,generating a <em class="emphasis">Makefile</em> from the <em class="emphasis">Makefile.PL</em> file and running<em class="emphasis">make</em>.</p><p><a name="INDEX-3733"></a><a name="INDEX-3734"></a>In order to verify that our extension works, we'll create a test suite in <em class="emphasis">test.pl</em>. This file is set up by <em class="emphasis">h2xs</em> to mimic thetest script that Perl itself has. Within the script, you may run tests to confirm that the extension behaves properly,printing <tt class="literal">ok</tt> when it does and <tt class="literal">not ok</tt> when it doesn't. Change theprint statement in the <tt class="literal">BEGIN</tt> block of <em class="emphasis">test.pl</em> to <tt class="literal">print "1..4\n";</tt>, and add the following code to the end of the file:<blockquote><pre class="programlisting">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";</pre></blockquote>The test script will be executed when you type <tt class="literal">make test</tt>.</p><h3 class="sect2">21.3.4. Using Functions from an External C Library</h3><p><a name="INDEX-3735"></a><a name="INDEX-3736"></a><a name="INDEX-3737"></a><a name="INDEX-3738"></a><a name="INDEX-3739"></a>So far, our two examples haven't relied on any C code outside of theXS file. Now we'll use some functions from the C math library:<blockquote><pre class="programlisting">voidround(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</pre></blockquote>Note that the <tt class="literal">round</tt> we define above does not return a value, butinstead changes the value of its argument in place.</p><p>The <em class="emphasis">floor</em>(3) and <em class="emphasis">ceil</em>(3) functions are part of the C math library. Ifyou were compiling a C program and needed to linkin the math library, you'd append <tt class="userinput"><b>-lm</b></tt> to the command line, so that's what you put intothe <tt class="literal">LIBS</tt> line in <em class="emphasis">Makefile.PL</em>:<blockquote><pre class="programlisting">'LIBS' => ['-lm'], # Link in the 'm' math library</pre></blockquote>Generate the <em class="emphasis">Makefile</em> and run <em class="emphasis">make</em>. Change the <tt class="literal">BEGIN</tt> block torun nine tests and add the following to <em class="emphasis">test.pl</em>:<blockquote><pre class="programlisting">$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";</pre></blockquote>Running <tt class="literal">make test</tt> should now print out that all nine tests are okay.</p><p>The <em class="emphasis">perlxstut</em> documentation bundled with Perl has several moreexamples of Perl extensions, including an example that uses <em class="emphasis">h2xs</em>to automatically make an entire C library available to Perl.</p><a name="INDEX-3740"></a><a name="INDEX-3741"></a><a name="INDEX-3742"></a><!-- BOTTOM NAV BAR --><hr width="515" align="left"><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="index.htm"><img src="../gifs/txthome.gif" alt="Home" border="0"></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><tr><td align="left" valign="top" width="172">21.2. Internal Data Types</td><td align="center" valign="top" width="171"><a href="index/index.htm"><img src="../gifs/index.gif" alt="Book Index" border="0"></a></td><td align="right" valign="top" width="172">21.4. Embedding Perl (Using Perl from C)</td></tr></table></div><hr width="515" align="left"><!-- LIBRARY NAV BAR --><img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p><font size="-1"><a href="copyrght.htm">Copyright © 2001</a> O'Reilly & Associates. All rights reserved.</font></p><map name="library-map"> <area shape="rect" coords="2,-1,79,99" href="../index.htm"><area shape="rect" coords="84,1,157,108" href="../perlnut/index.htm"><area shape="rect" coords="162,2,248,125" href="../prog/index.htm"><area shape="rect" coords="253,2,326,130" href="../advprog/index.htm"><area shape="rect" coords="332,1,407,112" href="../cookbook/index.htm"><area shape="rect" coords="414,2,523,103" href="../sysadmin/index.htm"></map><!-- END OF BODY --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -