📄 ch21_04.htm
字号:
<html><head><title>Embedding Perl (Using Perl from C) (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="Embedding Perl (Using Perl from C)"><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_03.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_05.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.4. Embedding Perl (Using Perl from C)</h2><a name="INDEX-3743"></a><a name="INDEX-3744"></a><a name="INDEX-3745"></a><a name="INDEX-3746"></a><a name="INDEX-3747"></a><a name="INDEX-3748"></a><p>You can access a Perl interpreter from C by <em class="emphasis">embedding</em> Perl insideyour C program. Since Perl is itself a C program, embedding consistsof taking the important chunks of Perl and integrating them into yours.</p><p>Note that embedding isn't necessary if your only goal is to use astandalone Perl program and you don't mind launching a separate process todo so. You can use a function like C's <em class="emphasis">popen</em>(3) to exchange databetween your C program and any external Perl program, just like you can usePerl's <tt class="literal">open(PIPE, "| program")</tt> or the <tt class="literal">IPC::Open2</tt> and<tt class="literal">IPC::Open3</tt> modules to exchange data between your Perl program andany other program. But if you want to avoid the overhead of launching a separate process,you can embed an interpreter into your C program.<a name="INDEX-3749"></a></p><p><a name="INDEX-3750"></a><a name="INDEX-3751"></a><a name="INDEX-3752"></a><a name="INDEX-3753"></a><a name="INDEX-3754"></a>When developing long-running applications (say, for embedding in a webserver), it's a good idea to maintain a single persistent interpreterrather than creating and destroying interpreters over and over again.The major reason is speed, since Perl will only be loaded into memoryonce. By using a persistent Perl interpreter, Apache's <tt class="literal">mod_perl</tt> module avoids loading Perl into memory anew every time someone hits an Apache web page. The <em class="emphasis">perlembed</em> manpage provides an exampleof a persistent interpreter, as well as an example of how a Perlprogram can manage multiple simultaneous interpreters (another bigplus for web servers).</p><h3 class="sect2">21.4.1. Compiling Embedded Programs</h3><a name="INDEX-3755"></a><a name="INDEX-3756"></a><a name="INDEX-3757"></a><a name="INDEX-3758"></a><a name="INDEX-3759"></a><p>When you embed Perl in C, your C program will usually allocate, "run",and deallocate a <tt class="literal">PerlInterpreter</tt> object, which is a C <tt class="literal">struct</tt> definedin the <em class="emphasis">libperl</em> library that was built in the process of configuringPerl for your system. The <em class="emphasis">libperl</em> library (along with <em class="emphasis">EXTERN.h</em>and <em class="emphasis">perl.h</em>, which you'll also need) resides in a directory that willvary from system to system. You should be able to find out the name ofthat directory with:<blockquote><pre class="programlisting">%<tt class="userinput"><b> perl -MConfig -e "print $Config{archlib}"</b></tt></pre></blockquote>You should compile your program in exactly the same way that your <em class="emphasis">perl</em>executable was compiled. First, you'll need to know what C compilerwas used to build Perl on your machine. You can learn that from:<blockquote><pre class="programlisting">%<tt class="userinput"><b> perl -MConfig -e "print $Config{cc}"</b></tt></pre></blockquote><a name="INDEX-3760"></a>You can figure out what to put on the rest of the command line withthe standard <tt class="literal">ExtUtils::Embed</tt> module. If you had aC program named <em class="emphasis">interp.c</em> and your C compiler was<em class="emphasis">cc</em>, you could compile it for embedding asfollows:<blockquote><pre class="programlisting">% <tt class="userinput"><b>cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`</b></tt></pre></blockquote></p><h3 class="sect2">21.4.2. Adding a Perl Interpreter to Your C Program</h3><p><a name="INDEX-3761"></a><a name="INDEX-3762"></a><a name="INDEX-3763"></a><a name="INDEX-3764"></a>As it turns out, <em class="emphasis">perl</em> (the C program) is a goodexample of embedding Perl (the language), so a simple demonstration ofembedding can be found in the file<em class="emphasis">miniperlmain.c</em>, included with the Perl sourcecode. Here's a nonportable version of<em class="emphasis">miniperlmain.c</em> containing the essentials ofembedding:<blockquote><pre class="programlisting">#include <EXTERN.h> /* from the Perl distribution */#include <perl.h> /* from the Perl distribution */static PerlInterpreter *my_perl; /*** The Perl interpreter ***/int main(int argc, char **argv, char **env){ my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, argc, argv, (char **)NULL); perl_run(my_perl); perl_destruct(my_perl); perl_free(my_perl);}</pre></blockquote>When this is compiled with the command line above, you'll be able touse <em class="emphasis">interp</em> just like a regular Perl interpreter:<blockquote><pre class="programlisting">% <tt class="userinput"><b>interp -e "printf('%x', 3735928559)"</b></tt>deadbeef</pre></blockquote>You can also execute Perl statements stored in a file by placing thefilename in <tt class="literal">argv[1]</tt> before calling<tt class="literal">perl_run</tt>.</p><h3 class="sect2">21.4.3. Calling a Perl Subroutine from C</h3><p><a name="INDEX-3765"></a><a name="INDEX-3766"></a><a name="INDEX-3767"></a>If a Perl program contains a subroutine that you want to call froma C program, you can create a Perl interpreter and then use one of thefunctions beginning with <tt class="literal">call_</tt> documented in the <em class="emphasis">perlcall</em> manpage to invokethe subroutine. Let's assume this is our Perl program, called<em class="emphasis">showtime.pl</em>:<blockquote><pre class="programlisting">print "I shan't be printed.";sub showtime { print time;}</pre></blockquote>In this example, we'll use <tt class="literal">call_argv</tt> to invoke the<tt class="literal">showtime</tt> subroutine from this C program, called<em class="emphasis">showtime.c</em>:<blockquote><pre class="programlisting">#include <EXTERN.h>#include <perl.h>static PerlInterpreter *my_perl;int main(int argc, char **argv, char **env){ char *args[] = { NULL }; my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, argc, argv, NULL); /*** skipping perl_run() ***/ call_argv("showtime", G_DISCARD | G_NOARGS, args); perl_destruct(my_perl); perl_free(my_perl);}</pre></blockquote>Here, we assume <tt class="literal">showtime</tt> is a Perl subroutine that takes noarguments (that's the <tt class="literal">G_NOARGS</tt>) and for which we can ignore thereturn value (that's the <tt class="literal">G_DISCARD</tt>). Those flags, and others, arediscussed in <em class="emphasis">perlcall</em>. We compile and run <em class="emphasis">showtime</em> as follows:<blockquote><pre class="programlisting">% <tt class="userinput"><b>cc -o showtime showtime.c `perl -MExtUtils::Embed -e ccopts -e ldopts`</b></tt>% <tt class="userinput"><b>showtime showtime.pl</b></tt>963852741</pre></blockquote>In this particular case, we don't call <tt class="literal">perl_run</tt>, but in general it'sconsidered good form so that <tt class="literal">DESTROY</tt> methods and <tt class="literal">END</tt> blocks areexecuted at the right time.</p><p>If you want to pass arguments to the Perl subroutine, you can add
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -