ch12_16.htm

来自「By Tom Christiansen and Nathan Torkingto」· HTM 代码 · 共 773 行

HTM
773
字号
<HTML><HEAD><TITLE>Recipe 12.15. Using h2xs to Make a Module with C Code (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:41:59Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch12_01.htm"TITLE="12. Packages, Libraries, and Modules"><LINKREL="prev"HREF="ch12_15.htm"TITLE="12.14. Using h2ph to Translate C #include Files"><LINKREL="next"HREF="ch12_17.htm"TITLE="12.16. Documenting Your Module with Pod"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch12_15.htm"TITLE="12.14. Using h2ph to Translate C #include Files"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 12.14. Using h2ph to Translate C #include Files"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch12_01.htm"TITLE="12. Packages, Libraries, and Modules"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch12_17.htm"TITLE="12.16. Documenting Your Module with Pod"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 12.16. Documenting Your Module with Pod"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch12-31357">12.15. Using h2xs to Make a Module with C Code</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1518">Problem</A></H3><PCLASS="para"><ACLASS="indexterm"NAME="ch12-idx-1000005283-0"></A><ACLASS="indexterm"NAME="ch12-idx-1000005283-1"></A><ACLASS="indexterm"NAME="ch12-idx-1000005283-2"></A>You'd like to access your system's unique C functions from Perl.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1524">Solution</A></H3><PCLASS="para">Use the <EMCLASS="emphasis">h2xs</EM> tool to generate the necessary template files, fill the files in appropriately, and then type:</P><PRECLASS="programlisting">% perl Makefile.PL% make</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1534">Discussion</A></H3><PCLASS="para">A Perl module need not be written solely in Perl. As with any other module, first pick a module name and use <EMCLASS="emphasis">h2xs</EM> on it. We'll make a <CODECLASS="literal">FineTime::time</CODE> function with the same semantics as in the previous recipe, but this time around, we'll implement it using real C.</P><PCLASS="para">First, we run the following command:</P><PRECLASS="programlisting">% h2xs -cn FineTime</PRE><PCLASS="para">If we had a <EMCLASS="emphasis">.h</EM> file with function prototype declarations, we could include that, but because we're writing this one from scratch, we'll use the <BCLASS="emphasis.bold">-c</B> flag to omit building code to translate any <CODECLASS="literal">#define</CODE> symbols. The <BCLASS="emphasis.bold">-n</B> flag says to create a module directory named <EMCLASS="emphasis">FineTime/</EM>, which will have the following files:</P><TABLECLASS="informaltable"BORDER="1"CELLPADDING="3"><THEADCLASS="thead"><TRCLASS="row"VALIGN="TOP"><THCLASS="entry"ALIGN="LEFT"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">Manifest</EM></P></TH><THCLASS="entry"ALIGN="LEFT"ROWSPAN="1"COLSPAN="1"><PCLASS="para">List of files in the distribution</P></TH></TR></THEAD><TBODYCLASS="tbody"><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">Changes</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">change log</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">Makefile.PL</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">a meta-makefile</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">FineTime.pm</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">the Perl parts</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">FineTime.xs</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">the soon-to-be C parts</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">test.pl</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">a test driver</P></TD></TR></TBODY></TABLE><PCLASS="para">Before we can type <CODECLASS="literal">make</CODE>, we'll have to generate a <CODECLASS="literal">Makefile</CODE> based on our system's configuration using the <EMCLASS="emphasis">Makefile.PL</EM> template. Here's how to do that:</P><PRECLASS="programlisting">% perl Makefile.PL</PRE><PCLASS="para">If the <ACLASS="indexterm"NAME="ch12-idx-1000005289-0"></A>XS code calls library code that isn't in the normal set of libraries Perl links from, add one more line to <EMCLASS="emphasis">Makefile.PL</EM> first. For example, if we wanted to link against the <EMCLASS="emphasis">librpm.a</EM> library, which lives in the <EMCLASS="emphasis">/usr/redhat/lib</EM> directory, we'd change the line of <EMCLASS="emphasis">Makefile.PL</EM> that reads:</P><PRECLASS="programlisting">'LIBS'      =&gt; [''],   # e.g., '-lm'</PRE><PCLASS="para">so that it says:</P><PRECLASS="programlisting">'LIBS'      =&gt; ['-L/usr/redhat/lib -lrpm'],</PRE><PCLASS="para">If the module is to be installed somewhere other than the local <EMCLASS="emphasis">site_lib</EM> directory, specify that on the command line:</P><PRECLASS="programlisting">% perl Makefile.PL LIB=~/perllib</PRE><PCLASS="para">Finally, edit the <EMCLASS="emphasis">FineTime.pm</EM> and <EMCLASS="emphasis">FineTime.xs</EM> files. In the first case, most of the work has been done for us. We just set up the export list with the function to be exported. This time we put it in <CODECLASS="literal">@EXPORT_OK</CODE> so that if the user wants the function, they must ask for it by name. Here's <EMCLASS="emphasis">FineTime.pm</EM>:</P><PRECLASS="programlisting">package FineTime;use strict;use vars qw($VERSION @ISA @EXPORT_OK);require Exporter;require DynaLoader;@ISA = qw(Exporter DynaLoader);@EXPORT_OK = qw(time);$VERSION = '0.01';bootstrap FineTime $VERSION;1;</PRE><PCLASS="para">The<ICLASS="filename"> make</I> process will automatically translate <EMCLASS="emphasis">FineTime.xs</EM> into a <EMCLASS="emphasis">FineTime.c</EM> file and eventually into a shared library, probably called <EMCLASS="emphasis">FineTime.so</EM> on most platforms. The utility that does this translation is <EMCLASS="emphasis">xsubpp</EM>, which is described in its own manpage and <ICLASS="filename">perlxstut </I>(1). The build will call <EMCLASS="emphasis">xsubpp</EM> automatically.</P><PCLASS="para">Besides a strong C background, you also need to understand the C-to-Perl interface, called XS (external subroutine). The details and nuances of XS are beyond the scope of this book. The automatically generated <EMCLASS="emphasis">FineTime.xs</EM> had the Perl-specific include files in it, as well as the MODULE declaration. We've added some extra includes and written the code for the new <CODECLASS="literal">time</CODE> function. Although this doesn't look entirely like C, it will, once <EMCLASS="emphasis">xsubpp</EM> gets done with it.</P><PCLASS="para">Here's the <EMCLASS="emphasis">FineTime.xs</EM> we used:</P><PRECLASS="programlisting">#include &lt;unistd.h&gt;#include &lt;sys/time.h&gt;#include &quot;EXTERN.h&quot;#include &quot;perl.h&quot;#include &quot;XSUB.h&quot;MODULE = FineTime           PACKAGE = FineTimedoubletime()    CODE:        struct timeval tv;        gettimeofday(&amp;tv,0);        RETVAL = tv.tv_sec + ((double) tv.tv_usec) / 1000000;    OUTPUT:        RETVAL</PRE><PCLASS="para">Defining a function by the same name as one from the standard C library won't cause a problem when it's compiled because that's not its real name. That's just what Perl calls it. The C linker will see it as <CODECLASS="literal">XS_FineTime_time</CODE>, so no conflict exists.</P><PCLASS="para">Here's what happened with make install (with some edits):</P><PRECLASS="programlisting">% make installmkdir ./blib/lib/auto/FineTimecp FineTime.pm ./blib/lib/FineTime.pm/usr/local/bin/perl -I/usr/lib/perl5/i686-linux/5.00403  -I/usr/lib/perl5/usr/lib/perl5/ExtUtils/xsubpp -typemap     /usr/lib/perl5/ExtUtils/typemap FineTime.xsFineTime.tc &amp;&amp; mv FineTime.tc FineTime.ccc -c -Dbool=char -DHAS_BOOL     -O2-DVERSION=\&quot;0.01\&quot; -DXS_VERSION=\&quot;0.01\&quot; -fpic     -I/usr/lib/perl5/i686-linux/5.00403/CORE  FineTime.cRunning Mkbootstrap for FineTime ()chmod 644 FineTime.bsLD_RUN_PATH=&quot;&quot; cc -o blib/arch/auto/FineTime/FineTime.so     -shared -L/usr/local/lib FineTime.ochmod 755 blib/arch/auto/FineTime/FineTime.socp FineTime.bs ./blib/arch/auto/FineTime/FineTime.bschmod 644 blib/arch/auto/FineTime/FineTime.bsInstalling /home/tchrist/perllib/i686-linux/./auto/FineTime/FineTime.soInstalling /home/tchrist/perllib/i686-linux/./auto/FineTime/FineTime.bsInstalling /home/tchrist/perllib/./FineTime.pmWriting /home/tchrist/perllib/i686-linux/auto/FineTime/.packlistAppending installation info to /home/tchrist/perllib/i686-linux/perllocal.pod</PRE><PCLASS="para">Once this is all done, we'll be able to type something like this into the shell:</P><PRECLASS="programlisting">% perl -I ~/perllib -MFineTime=time -le '1 while print time()' | head<CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.090978</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.09132</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.091389</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.091453</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.091515</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.091577</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.091639</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.0917</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.091763</I></CODE></B></CODE><CODECLASS="userinput"><B><CODECLASS="replaceable"><I>888177070.091864</I></CODE></B></CODE><ACLASS="indexterm"NAME="ch12-idx-1000005291-0"></A><ACLASS="indexterm"NAME="ch12-idx-1000005291-1"></A><ACLASS="indexterm"NAME="ch12-idx-1000005291-2"></A></PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1714">See Also</A></H3><PCLASS="para">Chapters 18 through 20 in <ACLASS="citetitle"HREF="../advprog/index.htm"TITLE="Advanced Perl Programming"><CITECLASS="citetitle">Advanced Perl Programming</CITE></A>; <ICLASS="filename">perlxstut </I>(1) and <ICLASS="filename">perlxs</I> (1) to learn how to call C from Perl; <ICLASS="filename">perlcall </I>(1) and <ICLASS="filename">perlguts</I> (1) to understand the internal Perl API; <ICLASS="filename">perlembed</I> (1) to learn how to call Perl from C; the the documentation for the standard ExtUtils::MakeMaker module, <ICLASS="filename">h2ph </I>(1) and <ICLASS="filename">xsubpp</I> (1); <ACLASS="systemitem.url"HREF="http://www.perl.com/CPAN/authors/Dean_Roehrich/">http://www.perl.com/CPAN/authors/Dean_Roehrich/</A>, which contains Dean's comprehensive XS cookbook that includes directions on interface with C++</P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch12_15.htm"TITLE="12.14. Using h2ph to Translate C #include Files"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 12.14. Using h2ph to Translate C #include Files"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch12_17.htm"TITLE="12.16. Documenting Your Module with Pod"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 12.16. Documenting Your Module with Pod"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">12.14. Using h2ph to Translate C #include Files</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">12.16. Documenting Your Module with Pod</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?