📄 ch26.htm
字号:
variable set to a constant value will probably let <TT><FONT FACE="Courier">make</FONT></TT>
process the makefile faster. I discuss this procedure in a moment.
In any event, the returned values from the call to use the <TT><FONT FACE="Courier">ExtUtils::embed</FONT></TT>
function are used to define the link libraries and include files.
The returned values can be used directly in makefiles should the
Perl <TT><FONT FACE="Courier">-e</FONT></TT> command not work
or if you prefer to use a <TT><FONT FACE="Courier">make</FONT></TT>
variable.
<P>
Listing 26.1 presents a sample makefile for the Linux machine.
<HR>
<BLOCKQUOTE>
<B>Listing 26.1. A sample makefile.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">1 IncK= -D__USE_BSD_SIGNAL -Dbool=char
-DHAS_BOOL <BR>
<FONT FACE="ZAPFDINGBATS">Â</FONT>-I/usr/local/include -rdynamic -I
/usr/lib/perl5/i486-linux/5.002/CORE<BR>
2 LIBK = -L/usr/local/lib /usr/lib/perl5/i486-linux/5.002
<BR>
<FONT FACE="ZAPFDINGBATS">Â</FONT>/auto/DynaLoader/DynaLoader.a -L/usr/lib/perl5/i486-linux/5.002/CORE
<BR>
<FONT FACE="ZAPFDINGBATS">Â</FONT>-lperl -lgdbm -ldbm -ldb -ldl -lm -lc -lbsd<BR>
3 K_LIBS = -lgdbm -ldbm -ldb -ldl -lm -lc -lbsd<BR>
4 <BR>
5 ex2 : ex2.c<BR>
6 $(cc) -fno-strict-prototype ex2.c
-o ex2 -L$(LIBK) -I$(IncK)</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Note the flags for the <TT><FONT FACE="Courier">gcc</FONT></TT>
compiler. The main problem with the <TT><FONT FACE="Courier">gcc</FONT></TT>
compiler is how the "safefree" function prototype is
declared in the <TT><FONT FACE="Courier">proto.h</FONT></TT> and
<TT><FONT FACE="Courier">handy.h</FONT></TT> files. There is a
slight difference in the syntax of each declaration, but programmatically
it makes no difference. To turn off the checking in <TT><FONT FACE="Courier">gcc</FONT></TT>,
simply use the <TT><FONT FACE="Courier">-fno-strict-prototype</FONT></TT>
flag at the command line for the <TT><FONT FACE="Courier">gcc</FONT></TT>
command.
<P>
The <TT><FONT FACE="Courier">LIBK</FONT></TT> and <TT><FONT FACE="Courier">IncK</FONT></TT>
paths are set to values that are derived from running the Perl
program shown in Listing 26.2. There is one possible problem you
must be aware of when you run this program: if you get errors
stating that it cannot find <TT><FONT FACE="Courier">embed.pm</FONT></TT>
in the <TT><FONT FACE="Courier">@Inc</FONT></TT> array, then modify
the <TT><FONT FACE="Courier">@Inc</FONT></TT> array to include
the path where the file is located. The commented lines in Listing
26.2 are examples.
<P>
If all else fails, copy the <TT><FONT FACE="Courier">embed.pm</FONT></TT>
path to the directory you happen to be in. If you get an error
stating that <TT><FONT FACE="Courier">embed.pm</FONT></TT> could
not be included or that it was empty, you have to modify the <TT><FONT FACE="Courier">embed.pm</FONT></TT>
file. Go to the statement with the <TT><FONT FACE="Courier">_END_</FONT></TT>
label and add the line <TT><FONT FACE="Courier">1;</FONT></TT>
before it. This step is only necessary if the <TT><FONT FACE="Courier">ExtUtils::embed</FONT></TT>
file could not be included.
<HR>
<BLOCKQUOTE>
<B>Listing 26.2. A sample makefile.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 <BR>
3 use ExtUtils::embed;<BR>
4 <BR>
5 #<BR>
6 # unshift(@Inc,"/usr/local/lib/perl5/site_perl");
<BR>
7 #<BR>
8 <BR>
9 &ccopts; # Create the path for headers
<BR>
10 &ldopts; # Create the path for libraries</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The call to the <TT><FONT FACE="Courier">&ccopts</FONT></TT>
function creates the include path for use with the <TT><FONT FACE="Courier">-I</FONT></TT>
flag. The call to <TT><FONT FACE="Courier">&ldopts</FONT></TT>
creates the path for libraries to be linked with the <TT><FONT FACE="Courier">-L</FONT></TT>
flag. Pipe the output to a saved file and create the makefile
as shown in Listing 26.1.
<H2><A NAME="AddingaPerlInterpreter"><B><FONT SIZE=5 COLOR=#FF0000>Adding
a Perl Interpreter to Your C Program</FONT></B></A></H2>
<P>
A C program using a Perl interpreter is really creating and running
a <TT><FONT FACE="Courier">PerlInterpreter</FONT></TT> object.
The <TT><FONT FACE="Courier">PerlInterpreter</FONT></TT> object
type is defined in the Perl library, and the C program simply
makes a reference to this library object. Several sample files
come in the <TT><FONT FACE="Courier">embed.pm</FONT></TT> file
and are used here as examples.
<P>
Listing 26.3 presents a quick example of how to embed a Perl interpreter
in a C program.
<HR>
<BLOCKQUOTE>
<B>Listing 26.3. The first example from the </B><TT><B><FONT FACE="Courier">embed.pm</FONT></B></TT><B>
module.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 /*<BR>
2 ** Sample program used from embed.pm module package.<BR>
3 */<BR>
4 #include <stdio.h><BR>
5 #include <EXTERN.h><BR>
6 #include <perl.h><BR>
7<BR>
8 static PerlInterpreter *my_perl;<BR>
9<BR>
10 main(int argc, char **argv, char **env)<BR>
11 {<BR>
12<BR>
13 my_perl
= perl_alloc();<BR>
14 perl_construct(my_perl);
<BR>
15 perl_parse(my_perl,
NULL, argc, argv, env);<BR>
16 perl_run(my_perl);
<BR>
17 perl_destruct(my_perl);
<BR>
18 perl_free(my_perl);
<BR>
19 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Lines 3 to 6 are the include headers you have to use to get this
to work. The <TT><FONT FACE="Courier">EXTERN.h</FONT></TT> and
<TT><FONT FACE="Courier">perl.h</FONT></TT> files will be picked
from where the Perl distribution is installed.
<P>
At line 8, the C program creates a pointer reference to the <TT><FONT FACE="Courier">PerlInterpreter</FONT></TT>
object defined in the Perl libraries. The reference will actually
be resolved in line 13 when the object is created.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">At line 10, the main program interface
is called. All three arguments are required. Do not use either
of these lines because they both caused compiler error, even with
the -fno-strict-prototypes flag set:<BR>
main(int argc, char **argv);<BR>
main(int argc, char *argv[], char *env[])</FONT></TT>
</BLOCKQUOTE>
<P>
Lines 14 and 15 construct the <TT><FONT FACE="Courier">PerlInterpreter</FONT></TT>
object and parse any environment variables and command-line arguments.
You can read and execute Perl statements from a file at any time
in a C program by simply placing the name of the file in <TT><FONT FACE="Courier">argv[1]</FONT></TT>
before calling the <TT><FONT FACE="Courier">perl_run</FONT></TT>
function. The <TT><FONT FACE="Courier">perl_run </FONT></TT>function
is called at line 16 in the sample code in Listing 26.2. The function
can be called repeatedly in the C code before the calls are made
to destruct and free the object (lines 17 and 18 in the sample
code).
<P>
Now <TT><FONT FACE="Courier">make</FONT></TT> this program, called
<TT><FONT FACE="Courier">ex2.c</FONT></TT>, and run it. In the
sample run that follows, note how variables are defined and used
interactively in this sample run:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$ <B>ex2<BR>
</B>$a = 1;<BR>
$b = 3;<BR>
print $a," ",$b," ",$a+$b,"\n";
<BR>
^D<BR>
1 3 4<BR>
$</FONT></TT>
</BLOCKQUOTE>
<P>
To run a script file, simply redirect the contents of a file into
the input of the interpreter. The file you are feeding into your
C mini-interpreter does not have to have its execute bit set in
its permissions. Here's a sample run.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$<B> cat test.pl<BR>
</B>$a = 1;<BR>
$b = 1;<BR>
print "a + b = ", $a + $b, "\n";<BR>
$<BR>
$ ex2 < test.pl<BR>
a + b = 2<BR>
$</FONT></TT>
</BLOCKQUOTE>
<P>
There you have it-a small Perl interpreter embedded in C code.
Once you have this interpreter embedded in your C code, you can
evaluate Perl statements by simply feeding them into the interpreter
one line at a time.
<P>
There will be occasions, though, when you simply want to call
a Perl subroutine directly from within the C code. I show you
how to do this in the next section.
<H2><A NAME="CallingPerlSubroutinesfromWithin"><B><FONT SIZE=5 COLOR=#FF0000>Calling
Perl Subroutines from Within a C Program</FONT></B></A></H2>
<P>
In order to call a Perl subroutine by name, simply replace the
call to <TT><FONT FACE="Courier">perl_run()</FONT></TT> with a
call to <TT><FONT FACE="Courier">perl_call_argv()</FONT></TT>.
An example is shown in the code in Listing 26.4.
<HR>
<BLOCKQUOTE>
<B>Listing 26.4. Calling a subroutine in Perl directly.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #include <stdio.h><BR>
2 #include <EXTERN.h><BR>
3 #include <perl.h><BR>
4<BR>
5 static PerlInterpreter *my_perl;
<BR>
6<BR>
7 int main(int argc, char **argv,
char **env)<BR>
8 {<BR>
9 my_perl
= perl_alloc();<BR>
10 perl_construct(my_perl);
<BR>
11<BR>
12 perl_parse(my_perl,
NULL, argc, argv, env);<BR>
13 /* The next line calls a function in the file named
in<BR>
14 * argv[1] of the program !!*/<BR>
15 perl_call_argv("showUser",
G_DISCARD | G_NOARGS, argv);<BR>
16 perl_destruct(my_perl);
<BR>
17 perl_free(my_perl);
<BR>
18 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Look closely at line 15. This is really the only line that is
different from the code shown in Listing 26.3. A Perl subroutine
called <TT><FONT FACE="Courier">showUser</FONT></TT> is being
called here. The <TT><FONT FACE="Courier">showUser</FONT></TT>
subroutine takes no arguments, so you specify a <TT><FONT FACE="Courier">G_NOARGS</FONT></TT>
flag, and returns no values, so specify the <TT><FONT FACE="Courier">G_DISCARD</FONT></TT>
flag. The <TT><FONT FACE="Courier">argv</FONT></TT> vector is
used to store the filename in <TT><FONT FACE="Courier">argv[1]</FONT></TT>.
To invoke this program, type the name of the file (<TT><FONT FACE="Courier">showMe.pl</FONT></TT>,
in this case) at the command line:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$ <B>ex3 showMe.pl<BR>
</B>Process 2689 : UID is 501 and GID is 501</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">showMe.pl</FONT></TT> file named
in <TT><FONT FACE="Courier">argv[1]</FONT></TT> is shown in Listing
26.5.
<HR>
<BLOCKQUOTE>
<B>Listing 26.5. The file containing the subroutine being called.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">1 #!/usr/bin/perl<BR>
2 sub showUser {<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -