You can access a Perl interpreter from C by embedding Perl inside your C program. Since Perl is itself a C program, embedding consists of taking the important chunks of Perl and integrating them into yours.
Note that embedding isn't necessary if your only goal is to use
a standalone Perl program and you don't mind launching a separate
process to do so. You can use a function like C's
popen (3) to exchange data between your
C program and any external Perl program, just like you can use Perl's
open(PIPE, "| program")
or the
IPC::Open2
and IPC::Open3
modules to exchange data between your Perl program and any other
program. But if you want to avoid the overhead of launching a separate
process, you can embed an interpreter into your C program.
When developing long-running applications (say, for
embedding in a web server), it's a good idea to maintain a single
persistent interpreter rather than creating and destroying
interpreters over and over again. The major reason is speed, since
Perl will only be loaded into memory once. By using a persistent Perl
interpreter, Apache's mod_perl
module avoids
loading Perl into memory anew every time someone hits an Apache web
page. The perlembed manpage provides an example
of a persistent interpreter, as well as an example of how a Perl
program can manage multiple simultaneous interpreters (another big
plus for web servers).
When you embed Perl in C, your C program will usually
allocate, "run", and deallocate a PerlInterpreter
object, which is a C struct
defined in the
libperl library that was built in the process
of configuring Perl for your system. The
libperl library (along with
EXTERN.h and perl.h, which
you'll also need) resides in a directory that will vary from system
to system. You should be able to find out the name of that directory
with:
% perl -MConfig -e "print $Config{archlib}"
You should compile your program in exactly the same way that your perl executable was compiled. First, you'll need to know what C compiler was used to build Perl on your machine. You can learn that from:
% perl -MConfig -e "print $Config{cc}"
You can figure out what to put on the rest of the
command line with the standard ExtUtils::Embed
module. If you had a C program named interp.c
and your C compiler was cc, you could compile
it for embedding as follows:
% cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
As it turns out, perl (the C program) is a good example of embedding Perl (the language), so a simple demonstration of embedding can be found in the file miniperlmain.c, included with the Perl source code. Here's a nonportable version of miniperlmain.c containing the essentials of embedding:
#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); }
When this is compiled with the command line above, you'll be able to use interp just like a regular Perl interpreter:
% interp -e "printf('%x', 3735928559)"
deadbeef
You can also execute Perl statements stored
in a file by placing the filename in argv[1]
before calling perl_run
.
If a Perl program contains a subroutine that you want
to call from a C program, you can create a Perl interpreter and then
use one of the functions beginning with call_
documented in the perlcall manpage to invoke
the subroutine. Let's assume this is our Perl program, called
showtime.pl:
print "I shan't be printed.";sub showtime { print time; }
In this example, we'll use
call_argv
to invoke the
showtime
subroutine from this C program, called
showtime.c:
#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); }
Here, we assume showtime
is a Perl
subroutine that takes no arguments (that's the
G_NOARGS
) and for which we can ignore the return
value (that's the G_DISCARD
). Those flags, and
others, are discussed in perlcall. We compile
and run showtime as follows:
%cc -o showtime showtime.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
%showtime showtime.pl
963852741
In this particular case, we don't call
perl_run
, but in general it's considered good
form so that DESTROY
methods and
END
blocks are executed at the right time.
If you want to pass arguments to the Perl subroutine, you can
add strings to the NULL
-terminated
args
list passed to call_argv
.
For other data types, or to examine return values, you'll need to
manipulate the Perl stack. That's touched on lightly later; for the
down and dirty, read the perlcall manpage
bundled with Perl.
Perl provides two functions for evaluating snippets
of Perl code: eval_sv
and
eval_pv
, described in the
perlapi manpage. Arguably, these are the only
routines you'll ever need to execute Perl code from within your C
program. The code executed can be as long as you wish, contain
multiple statements, and employ use
,
require
, or do
to include
other Perl files.
eval_pv
lets you evaluate individual Perl
strings and then extract variables for coercion into C types. The
following program, string.c, executes three
Perl strings, extracting an int
from the first, a
float
from the second, and a char
*
from the third:
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; main (int argc, char **argv, char **env) { STRLEN n_a; char *embedding[] = { "", "-e", "0" }; my_perl = perl_alloc(); perl_construct( my_perl ); perl_parse(my_perl, NULL, 3, embedding, NULL); perl_run(my_perl); /** Treat $a as an integer **/ eval_pv("$a = 3; $a **= 2", TRUE); printf("a = %d ", SvIV(get_sv("a", FALSE))); /** Treat $a as a float **/ eval_pv("$a = 3.14; $a **= 2", TRUE); printf("a = %f ", SvNV(get_sv("a", FALSE))); /** Treat $a as a string **/ eval_pv("$a = 'relreP kcaH rehtonA tsuJ'; $a = reverse($a);", TRUE); printf("a = %s ", SvPV(get_sv("a", FALSE), n_a)); perl_destruct(my_perl); perl_free(my_perl); }
All of the functions with Sv
in
their names convert Perl scalars to C types. They're described in
the perlguts and perlapi
manpages. If you compile and run this program, you'll see the
results of using SvIV
to create an
int
, SvNV
to create a
float
, and SvPV
to create a C
string:
a = 9 a = 9.859600 a = Just Another Hack Perler
In the previous example, we've created a global variable to
temporarily store the computed value of our evaluated expression. It
is also possible (and in most cases better form) to use the return
value of eval_pv
instead of throwing it
away:
SV *val = eval_pv("reverse 'relreP kcaH rehtonA tsuJ'", TRUE); printf("%s ", SvPV(val,n_a));
The perlembed manpage bundled
with Perl includes a demonstration of eval_sv
that lets you make use of Perl's regular expression capabilities
from your C program.
When trying to explain stacks, most computer science textbooks[2] mumble something about spring-loaded columns of cafeteria plates: the last thing you pushed on the stack is the first thing you pop off. That'll do for our purposes: your C program will push some arguments onto "the Perl stack", shut its eyes while some magic happens, and then pop the results--the return value of your Perl subroutine--off the stack.
We'll present an example here without much
explanation. To really understand what's going on, you'll need to
know how to convert between C types and Perl types, with
newSViv
and sv_setnv
and
newAV
and all their friends described in the
perlguts and perlapi
manpages. Then you'll need to read perlcall to
learn how to manipulate the Perl stack.
Because C has no built-in function for integer
exponentiation, let's make Perl's **
operator
available to it. (This is less useful than it sounds, since Perl
implements **
with C's pow
(3) function.) First we'll create an exponentiation
function in a library file called
power.pl:
sub expo { my ($a, $b) = @_; return $a ** $b; }
Now we'll create a C program, power.c,
with a function called PerlPower
that pushes the
two arguments onto the stack, invokes expo
, and
pops the return value out:
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; /* "Real programmers can write assembly code in any language." */ static void PerlPower(int a, int b) { dSP; /* initialize stack pointer */ ENTER; /* everything created after here */ SAVETMPS; /* …is a temporary variable. */ PUSHMARK(SP); /* remember the stack pointer */ XPUSHs(sv_2mortal(newSViv(a))); /* push the base onto the stack */ XPUSHs(sv_2mortal(newSViv(b))); /* push the exponent onto stack */ PUTBACK; /* make local stack pointer global */ call_pv("expo", G_SCALAR); /* call the function */ SPAGAIN; /* refresh stack pointer */ /* pop the return value from stack */ printf ("%d to the %dth power is %d. ", a, b, POPi); PUTBACK; FREETMPS; /* free that return value */ LEAVE; /* …and the XPUSHed "mortal" args */ }int main (int argc, char **argv, char **env) { char *my_argv[] = { "", "power.pl" }; my_perl = perl_alloc(); perl_construct( my_perl ); perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL); perl_run(my_perl); PerlPower(3, 4); /*** Compute 3 ** 4 ***/ perl_destruct(my_perl); perl_free(my_perl); }
You can compile power.c into power like so:
%cc -o power power.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
%power
3 to the 4th power is 81.
Now your power program can sit around being different too.