Mailing List Archive

new perlembed
3c3
< perlembed - how to embed perl in your C or C++ app
---
> perlembed - how to embed perl in your C program
5c5,297
< =head1 DESCRIPTION
---
> =head1 PREAMBLE
>
> Do you want to:
>
> =over 5
>
> =item B<Use C from Perl?>
>
> Read L<perlcall> and L<perlxs>.
>
> =item B<Use a UNIX program from Perl?>
>
> Read about backquotes and L<perlfunc/system> and L<perlfunc/exec>.
>
> =item B<Use Perl from Perl?>
>
> Read about L<perlfunc/do> and L<perlfunc/eval> and L<perlmod/use>
> and L<perlmod/require>.
>
> =item B<Use C from C?>
>
> Rethink your design.
>
> =item B<Use Perl from C?>
>
> Read on...
>
> =back
>
> =head1 ROADMAP
>
> There's one example in each of the three sections:
>
> L<Adding a Perl interpreter to your C program>
>
> L<Calling a Perl subroutine from your C program>
>
> L<Fiddling with the Perl stack from your C program>
>
> This documentation is UNIX specific.
>
> =head1 EXPLANATION
>
> Every C program that uses Perl must link in the I<perl library>.
>
> What's that, you ask? Perl is itself written in C; the perl
> library is the collection of compiled C programs that were used to
> create your perl executable (I</usr/bin/perl> or equivalent).
> (Corollary: you can't use Perl from C unless Perl has been compiled
> on your machine, or installed properly---that's why you shouldn't
> blithely copy Perl executables from machine to machine without also
> copying the I<lib> directory.)
>
> Your C program will---usually---allocate, "run", and deallocate a
> I<PerlInterpreter> object, which is defined in the perl library.
>
> =head2 Adding a Perl interpreter to your C program
>
> In a sense, perl (the C program) is a good example of embedding Perl
> (the language), so I'll demonstrate embedding with I<miniperlmain.c>,
> from the source distribution. Here's a bastardized version of
> I<miniperlmain.c> containing the essentials of embedding:
>
> #include <stdio.h>
> #include <EXTERN.h> /* from the Perl distribution */
> #include <perl.h> /* from the Perl distribution */
>
> static void xs_init _((void));
> static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
>
> int main(int argc, char **argv, char **env)
> {
> int status;
>
> my_perl = perl_alloc();
> perl_construct(my_perl);
>
> status = perl_parse(my_perl, xs_init, argc, argv, env);
> if (status) exit(status);
>
> status = perl_run(my_perl);
> perl_destruct(my_perl);
> perl_free(my_perl);
>
> exit(status);
> }
>
> static void xs_init() {}
>
> If your copy of Perl is recent enough to contain this documentation
> (5.002 or later), then the perl library (and EXTERN.h and perl.h) will
> reside in a directory resembling this:
>
> /usr/local/lib/perl5/your_architecture_here/CORE
>
>
> Here's how you might compile the above program (say it's called I<interp.c>)
> on a DEC Alpha running the OSF operating system:
>
> % cc -o interp interp.c -L/usr/local/lib/perl5/alpha-dec_osf/CORE
> -I/usr/local/lib/perl5/alpha-dec_osf/CORE -lperl -lm
>
> You'll have to choose the appropriate compiler (I<cc>, I<gcc>, et al.) and
> library directory (I</usr/local/lib/...>) for your machine. If your
> compiler complains that certain functions are undefined, or that it
> can't locate I<-lperl>, then you need to change the path following the
> -L. If it complains that it can't find EXTERN.h or perl.h, you need
> to change the path following the -I.
>
> After a successful compilation, you'll be able to use I<interp> just
> like perl itself:
>
> % interp
> print "Pretty Good Perl \n";
> print "10890 - 9801 is ", 10890 - 9801;
> <CTRL-D>
> Pretty Good Perl
> 10890 - 9801 is 1089
>
> or
>
> % interp -e 'printf("%x", 3735928559)'
> deadbeef
>
> You can also read and execute Perl statements from a file while in the
> midst of your C program, by placing the filename in I<argv[1]> before
> calling I<perl_run()>.
>
> =head2 Calling a Perl subroutine from your C program
>
> To call individual Perl subroutines, you'll need to remove the call to
> I<perl_run()> and replace it with a new function: I<perl_call_argv()>.
>
> That's shown below, in a program I'll call I<showtime.c>.
>
> #include <stdio.h>
> #include <EXTERN.h>
> #include <perl.h>
>
> static void xs_init _((void));
> static PerlInterpreter *my_perl;
>
> int main(int argc, char **argv, char **env)
> {
> int status;
>
> my_perl = perl_alloc();
> perl_construct(my_perl);
>
> status = perl_parse(my_perl, xs_init, argc, argv, env);
> if (status) exit(status);
>
> /*** This replaces perl_run() ***/
> perl_call_argv("showtime", G_DISCARD | G_NOARGS, argv);
> perl_destruct(my_perl);
> perl_free(my_perl);
>
> exit(status);
> }
>
> static void xs_init() {}
>
> where I<showtime> is a Perl subroutine that takes no arguments (that's the
> I<G_NOARGS>) and for which I'll ignore the return value (that's the
> I<G_DISCARD>). Those flags, and others, are discussed in L<perlcall>.
>
> I'll define the I<showtime> subroutine in a file called I<showtime.pl>:
>
> print "I shan't be printed.";
>
> sub showtime {
> print time;
> }
>
> Simple enough. Now compile and run:
>
> % cc -o showtime showtime.c -L/usr/local/lib/perl5/alpha-dec_osf/CORE
> -I/usr/local/lib/perl5/alpha-dec_osf/CORE -lperl -lm
>
> % showtime showtime.pl
> 818284590
>
> yielding the number of seconds that elapsed between January 1, 1970
> (the beginning of the UNIX Epoch), and the moment I began writing this
> sentence.
>
> If you want to pass some arguments to the Perl subroutine, or
> you want to access the return value, you'll need to manipulate the
> Perl stack.
>
> =head2 Fiddling with the Perl stack from your C program
>
> When trying to explain stacks, most computer science textbooks 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.
>
> First 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. They're described in L<perlguts>.
>
> Then you'll need to know how to manipulate the Perl stack. That's
> described in L<perlcall>.
>
> Once you've understood those, embedding Perl in C is easy.
>
> Since C has no built-in function for integer exponentiation, let's
> make Perl's ** operator available to it (although most Perl arithmetic
> is computed with double-precision floats anyway). First I'll create a
> stub exponentiation function in I<power.pl>:
>
> sub expo {
> my ($a, $b) = @_;
> return $a ** $b;
> }
>
> Now I'll create a C program, I<power.c>, with a function
> I<PerlPower()> that contains all the perlguts necessary to push the
> two arguments into I<expo()> and to pop the return value out. Take a
> deep breath...
>
> #include <stdio.h>
> #include <EXTERN.h>
> #include <perl.h>
>
> static void xs_init _((void));
> static PerlInterpreter *my_perl;
>
> 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 */
> perl_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.\n", 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[2];
>
> my_perl = perl_alloc();
> perl_construct( my_perl );
>
> my_argv[1] = (char *) malloc(10);
> sprintf(my_argv[1], "power.pl");
>
> perl_parse(my_perl, xs_init, argc, my_argv, env);
>
> PerlPower(3, 4); /*** Compute 3 ** 4 ***/
>
> perl_destruct(my_perl);
> perl_free(my_perl);
> }
>
> static void xs_init() {}
>
> Compile and run:
>
> % cc -o power power.c -L/usr/local/lib/perl5/alpha-dec_osf/CORE
> -I/usr/local/lib/perl5/alpha-dec_osf/CORE -lperl -lm
>
> % power power.pl
> 3 to the 4th power is 81.
>
>
> MORAL: you can sometimes L<write faster code> in C, but
> you can always L<write code faster> in Perl. Since you can use
> each from the other, combine them as you wish.
>
>
> =head1 AUTHOR
>
> Jon Orwant
>
> L<orwant@media.mit.edu>
>
> December 12, 1995
>
> Some of this material is excerpted from my book: I<Perl 5 Interactive>, Waite
> Group Press, 1996. ISBN 1-57169-064-6.
7d298
< Look at perlmain.c, and do something like that.