*nix Documentation Project
·  Home
 +   man pages
·  Linux HOWTOs
·  FreeBSD Tips
·  *niX Forums

  man pages->IRIX man pages -> perlembed (1)              
Title
Content
Arch
Section
 

Contents


PERLEMBED(1)							  PERLEMBED(1)


NAME    [Toc]    [Back]

     perlembed - how to	embed perl in your C program

DESCRIPTION    [Toc]    [Back]

     PREAMBLE

     Do	you want to:

     Use C from	Perl?
	  Read the perlcall manpage and	the perlxs manpage.

     Use a Unix	program	from Perl?
	  Read about back-quotes and about system and exec in the perlfunc
	  manpage.

     Use Perl from Perl?
	  Read about the do entry in the perlfunc manpage and the eval entry
	  in the perlfunc manpage and the require entry	in the perlfunc
	  manpage and the use entry in the perlfunc manpage.

     Use C from	C?
	  Rethink your design.

     Use Perl from C?
	  Read on...

     ROADMAP    [Toc]    [Back]

     the section on Compiling your C program

     There's one example in each of the	nine sections:

     the section on Adding a Perl interpreter to your C	program

     the section on Calling a Perl subroutine from your	C program

     the section on Evaluating a Perl statement	from your C program

     the section on Performing Perl pattern matches and	substitutions from
     your C program

     the section on Fiddling with the Perl stack from your C program

     the section on Maintaining	a persistent interpreter

     the section on Maintaining	multiple interpreter instances

     the section on Using Perl modules,	which themselves use C libraries, from
     your C program






									Page 1






PERLEMBED(1)							  PERLEMBED(1)



     the section on Embedding Perl under Win32

     Compiling your C program    [Toc]    [Back]

     If	you have trouble compiling the scripts in this documentation, you're
     not alone.	 The cardinal rule: COMPILE THE	PROGRAMS IN EXACTLY THE	SAME
     WAY THAT YOUR PERL	WAS COMPILED.  (Sorry for yelling.)

     Also, every C program that	uses Perl must link in the 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	(/usr/bin/perl or equivalent).	(Corollary: you	can't use Perl
     from your C program 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 lib
     directory.)

     When you use Perl from C, your C program will--usually--allocate, "run",
     and deallocate a PerlInterpreter object, which is defined by the perl
     library.

     If	your copy of Perl is recent enough to contain this documentation
     (version 5.002 or later), then the	perl library (and EXTERN.h and perl.h,
     which you'll also need) will reside in a directory	that looks like	this:

	 /usr/local/lib/perl5/your_architecture_here/CORE

     or	perhaps	just

	 /usr/local/lib/perl5/CORE

     or	maybe something	like

	 /usr/opt/perl5/CORE

     Execute this statement for	a hint about where to find CORE:

	 perl -MConfig -e 'print $Config{archlib}'

     Here's how	you'd compile the example in the next section, the section on
     Adding a Perl interpreter to your C program, on my	Linux box:

	 % gcc -O2 -Dbool=char -DHAS_BOOL -I/usr/local/include
	 -I/usr/local/lib/perl5/i586-linux/5.003/CORE
	 -L/usr/local/lib/perl5/i586-linux/5.003/CORE
	 -o interp interp.c -lperl -lm

     (That's all one line.)  On	my DEC Alpha running 5.003_05, the incantation
     is	a bit different:






									Page 2






PERLEMBED(1)							  PERLEMBED(1)



	 % cc -O2 -Olimit 2900 -DSTANDARD_C -I/usr/local/include
	 -I/usr/local/lib/perl5/alpha-dec_osf/5.00305/CORE
	 -L/usr/local/lib/perl5/alpha-dec_osf/5.00305/CORE -L/usr/local/lib
	 -D__LANGUAGE_C__ -D_NO_PROTO -o interp	interp.c -lperl	-lm

     How can you figure	out what to add?  Assuming your	Perl is	post-5.001,
     execute a perl -V command and pay special attention to the	"cc" and
     "ccflags" information.

     You'll have to choose the appropriate compiler (cc, gcc, et al.) for your
     machine: perl -MConfig -e 'print $Config{cc}' will	tell you what to use.

     You'll also have to choose	the appropriate	library	directory
     (/usr/local/lib/...) for your machine.  If	your compiler complains	that
     certain functions are undefined, or that it can't locate -lperl, then you
     need to change the	path following the -L.	If it complains	that it	can't
     find EXTERN.h and perl.h, you need	to change the path following the -I.

     You may have to add extra libraries as well.  Which ones?	Perhaps	those
     printed by

	perl -MConfig -e 'print	$Config{libs}'

     Provided your perl	binary was properly configured and installed the
     ExtUtils::Embed module will determine all of this information for you:

	% cc -o	interp interp.c	`perl -MExtUtils::Embed	-e ccopts -e ldopts`

     If	the ExtUtils::Embed module isn't part of your Perl distribution, you
     can retrieve it from http://www.perl.com/perl/CPAN/modules/by-
     module/ExtUtils::Embed.  (If this documentation came from your Perl
     distribution, then	you're running 5.004 or	better and you already have
     it.)

     The ExtUtils::Embed kit on	CPAN also contains all source code for the
     examples in this document,	tests, additional examples and other
     information you may find useful.

     Adding a Perl interpreter to your C program    [Toc]    [Back]

     In	a sense, perl (the C program) is a good	example	of embedding Perl (the
     language),	so I'll	demonstrate embedding with miniperlmain.c, from	the
     source distribution.  Here's a bastardized, 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	   ***/






									Page 3






PERLEMBED(1)							  PERLEMBED(1)



	 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);
	 }

     Notice that we don't use the env pointer.	Normally handed	to perl_parse
     as	its final argument, env	here is	replaced by NULL, which	means that the
     current environment will be used.

     Now compile this program (I'll call it interp.c) into an executable:

	 % cc -o interp	interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`

     After a successful	compilation, you'll be able to use 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 argv[1] before
     calling perl_run().

     Calling a Perl subroutine from your C program    [Toc]    [Back]

     To	call individual	Perl subroutines, you can use any of the perl_call_*
     functions documented in the the perlcall manpage manpage.	In this
     example we'll use perl_call_argv.

     That's shown below, in a program I'll call	showtime.c.

	 #include <EXTERN.h>
	 #include <perl.h>

	 static	PerlInterpreter	*my_perl;






									Page 4






PERLEMBED(1)							  PERLEMBED(1)



	 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() ***/

	     perl_call_argv("showtime",	G_DISCARD | G_NOARGS, args);

	     perl_destruct(my_perl);
	     perl_free(my_perl);
	 }

     where showtime is a Perl subroutine that takes no arguments (that's the
     G_NOARGS) and for which I'll ignore the return value (that's the
     G_DISCARD).  Those	flags, and others, are discussed in the	perlcall
     manpage.

     I'll define the showtime subroutine in a file called showtime.pl:

	 print "I shan't be printed.";

	 sub showtime {
	     print time;
	 }

     Simple enough.  Now compile and run:

	 % cc -o showtime showtime.c `perl -MExtUtils::Embed -e	ccopts -e ldopts`

	 % 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.

     In	this particular	case we	don't have to call perl_run, but in general
     it's considered good practice to ensure proper initialization of library
     code, including execution of all object DESTROY methods and package END
     {}	blocks.

     If	you want to pass arguments to the Perl subroutine, you can add strings
     to	the NULL-terminated args list passed to	perl_call_argv.	 For other
     data types, or to examine return values, you'll need to manipulate	the
     Perl stack.  That's demonstrated in the last section of this document:
     the section on Fiddling with the Perl stack from your C program.





									Page 5






PERLEMBED(1)							  PERLEMBED(1)



     Evaluating	a Perl statement from your C program

     Perl provides two API functions to	evaluate pieces	of Perl	code.  These
     are the perl_eval_sv() entry in the perlguts manpage and the
     perl_eval_pv() entry in the perlguts manpage.

     Arguably, these are the only routines you'll ever need to execute
     snippets of Perl code from	within your C program.	Your code can be as
     long as you wish; it can contain multiple statements; it can employ the
     use entry in the perlfunc manpage,	the require entry in the perlfunc
     manpage and the do	entry in the perlfunc manpage to include external Perl
     files.

     perl_eval_pv() lets us 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)
	{
	    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 **/
	    perl_eval_pv("$a = 3; $a **= 2", TRUE);
	    printf("a =	%d\n", SvIV(perl_get_sv("a", FALSE)));

	    /**	Treat $a as a float **/
	    perl_eval_pv("$a = 3.14; $a	**= 2",	TRUE);
	    printf("a =	%f\n", SvNV(perl_get_sv("a", FALSE)));

	    /**	Treat $a as a string **/
	    perl_eval_pv("$a = 'rekcaH lreP rehtonA tsuJ'; $a =	reverse($a);", TRUE);
	    printf("a =	%s\n", SvPV(perl_get_sv("a", FALSE), na));

	    perl_destruct(my_perl);
	    perl_free(my_perl);
	}

     All of those strange functions with sv in their names help	convert	Perl
     scalars to	C types.  They're described in the perlguts manpage.




									Page 6






PERLEMBED(1)							  PERLEMBED(1)



     If	you compile and	run string.c, you'll see the results of	using SvIV()
     to	create an int, SvNV() to create	a float, and SvPV() to create a
     string:

	a = 9
	a = 9.859600
	a = Just Another Perl Hacker

     In	the example above, we've created a global variable to temporarily
     store the computed	value of our eval'd expression.	 It is also possible
     and in most cases a better	strategy to fetch the return value from	the
     perl_eval_pv manpage instead.  Example:

	...
	SV *val	= perl_eval_pv("reverse	'rekcaH	lreP rehtonA tsuJ'", TRUE);
	printf("%s\n", SvPV(val,na));
	...

     This way, we avoid	namespace pollution by not creating global variables
     and we've simplified our code as well.

     Performing	Perl pattern matches and substitutions from your C program

     The perl_eval_sv()	function lets us evaluate chunks of Perl code, so we
     can define	some functions that use	it to "specialize" in matches and
     substitutions: match(), substitute(), and matches().

	char match(SV *string, char *pattern);

     Given a string and	a pattern (e.g., m/clasp/ or /\b\w*\b/,	which in your
     C program might appear as "/\\b\\w*\\b/"),	match()	returns	1 if the
     string matches the	pattern	and 0 otherwise.

	int substitute(SV **string, char *pattern);

     Given a pointer to	an SV and an =~	operation (e.g., s/bob/robert/g	or
     tr[A-Z][a-z]), substitute() modifies the string within the	AV at
     according to the operation, returning the number of substitutions made.

	int matches(SV *string,	char *pattern, AV **matches);

     Given an SV, a pattern, and a pointer to an empty AV, matches() evaluates
     $string =~	$pattern in an array context, and fills	in matches with	the
     array elements, returning the number of matches found.

     Here's a sample program, match.c, that uses all three (long lines have
     been wrapped here):








									Page 7






PERLEMBED(1)							  PERLEMBED(1)



      #include <EXTERN.h>
      #include <perl.h>

      /** my_perl_eval_sv(code,	error_check)
      ** kinda like perl_eval_sv(),
      ** but we	pop the	return value off the stack
      **/
      SV* my_perl_eval_sv(SV *sv, I32 croak_on_error)
      {
	  dSP;
	  SV* retval;

	  PUSHMARK(sp);
	  perl_eval_sv(sv, G_SCALAR);

	  SPAGAIN;
	  retval = POPs;
	  PUTBACK;

	  if (croak_on_error &&	SvTRUE(GvSV(errgv)))
	     croak(SvPVx(GvSV(errgv), na));

	  return retval;
      }

      /** match(string,	pattern)
      **
      ** Used for matches in a scalar context.
      **
      ** Returns 1 if the match	was successful;	0 otherwise.
      **/

      I32 match(SV *string, char *pattern)
      {
	  SV *command =	newSV(0), *retval;

	  sv_setpvf(command, "my $string = '%s'; $string =~ %s",
		   SvPV(string,na), pattern);

	  retval = my_perl_eval_sv(command, TRUE);
	  SvREFCNT_dec(command);

	  return SvIV(retval);
      }

      /** substitute(string, pattern)
      **
      ** Used for =~ operations	that modify their left-hand side (s/// and tr///)
      **
      ** Returns the number of successful matches, and
      ** modifies the input string if there were any.
      **/



									Page 8






PERLEMBED(1)							  PERLEMBED(1)




      I32 substitute(SV	**string, char *pattern)
      {
	  SV *command =	newSV(0), *retval;

	  sv_setpvf(command, "$string =	'%s'; ($string =~ %s)",
		   SvPV(*string,na), pattern);

	  retval = my_perl_eval_sv(command, TRUE);
	  SvREFCNT_dec(command);

	  *string = perl_get_sv("string", FALSE);
	  return SvIV(retval);
      }

      /** matches(string, pattern, matches)
      **
      ** Used for matches in an	array context.
      **
      ** Returns the number of matches,
      ** and fills in **matches	with the matching substrings
      **/

      I32 matches(SV *string, char *pattern, AV	**match_list)
      {
	  SV *command =	newSV(0);
	  I32 num_matches;

	  sv_setpvf(command, "my $string = '%s'; @array	= ($string =~ %s)",
		   SvPV(string,na), pattern);

	  my_perl_eval_sv(command, TRUE);
	  SvREFCNT_dec(command);

	  *match_list =	perl_get_av("array", FALSE);
	  num_matches =	av_len(*match_list) + 1; /** assume $[ is 0 **/

	  return num_matches;
      }

      main (int	argc, char **argv, char	**env)
      {
	  PerlInterpreter *my_perl = perl_alloc();
	  char *embedding[] = {	"", "-e", "0" };
	  AV *match_list;
	  I32 num_matches, i;
	  SV *text = newSV(0);

	  perl_construct(my_perl);
	  perl_parse(my_perl, NULL, 3, embedding, NULL);

	  sv_setpv(text, "When he is at	a convenience store and	the bill comes to some amount like 76 cents, Maynard is	aware that there is something he *should* do, something	that will enable him to	get back a quarter, but	he has no idea *what*.	He fumbles through his red squeezey changepurse	and gives the boy three	extra pennies with his dollar, hoping that he might luck into the correct amount.  The boy gives him back two of his own pennies and then the big shiny	quarter	that is	his prize. -RICHH");



									Page 9






PERLEMBED(1)							  PERLEMBED(1)




	  if (match(text, "m/quarter/")) /** Does text contain 'quarter'? **/
	     printf("match: Text contains the word 'quarter'.\n\n");
	  else
	     printf("match: Text doesn't contain the word 'quarter'.\n\n");

	  if (match(text, "m/eighth/"))	/** Does text contain 'eighth'?	**/
	     printf("match: Text contains the word 'eighth'.\n\n");
	  else
	     printf("match: Text doesn't contain the word 'eighth'.\n\n");

	  /** Match all	occurrences of /wi../ **/
	  num_matches =	matches(text, "m/(wi..)/g", &match_list);
	  printf("matches: m/(wi..)/g found %d matches...\n", num_matches);

	  for (i = 0; i	< num_matches; i++)
	     printf("match: %s\n", SvPV(*av_fetch(match_list, i, FALSE),na));
	  printf("\n");

	  /** Remove all vowels	from text **/
	  num_matches =	substitute(&text, "s/[aeiou]//gi");
	  if (num_matches) {
	     printf("substitute: s/[aeiou]//gi...%d substitutions made.\n",
		    num_matches);
	     printf("Now text is: %s\n\n", SvPV(text,na));
	  }

	  /** Attempt a	substitution **/
	  if (!substitute(&text, "s/Perl/C/")) {
	     printf("substitute: s/Perl/C...No substitution made.\n\n");
	  }

	  SvREFCNT_dec(text);
	  perl_destruct_level =	1;
	  perl_destruct(my_perl);
	  perl_free(my_perl);
      }

     which produces the	output (again, long lines have been wrapped here)

	match: Text contains the word 'quarter'.

	match: Text doesn't contain the	word 'eighth'.

	matches: m/(wi..)/g found 2 matches...
	match: will
	match: with








								       Page 10






PERLEMBED(1)							  PERLEMBED(1)



	substitute: s/[aeiou]//gi...139	substitutions made.
	Now text is: Whn h s t	cnvnnc str nd th bll cms t sm mnt lk 76	cnts,
	Mynrd s	wr tht thr s smthng h *shld* d,	smthng tht wll nbl hm t	gt bck
	qrtr, bt h hs n	d *wht*.  H fmbls thrgh	hs rd sqzy chngprs nd gvs th by
	thr xtr	pnns wth hs dllr, hpng tht h mght lck nt th crrct mnt.	Th by gvs
	hm bck tw f hs wn pnns nd thn th bg shny qrtr tht s hs prz. -RCHH

	substitute: s/Perl/C...No substitution made.


     Fiddling with the Perl stack from your C program    [Toc]    [Back]

     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 the perlguts manpage.

     Then you'll need to know how to manipulate	the Perl stack.	 That's
     described in the perlcall manpage.

     Once you've understood those, embedding Perl in C is easy.

     Because C has no builtin function for integer exponentiation, let's make
     Perl's ** operator	available to it	(this is less useful than it sounds,
     because Perl implements **	with C's pow() function).  First I'll create a
     stub exponentiation function in power.pl:

	 sub expo {
	     my	($a, $b) = @_;
	     return $a ** $b;
	 }

     Now I'll create a C program, power.c, with	a function PerlPower() that
     contains all the perlguts necessary to push the two arguments into	expo()
     and to pop	the return value out.  Take a deep breath...

	 #include <EXTERN.h>
	 #include <perl.h>

	 static	PerlInterpreter	*my_perl;









								       Page 11






PERLEMBED(1)							  PERLEMBED(1)



	 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[] = { "", "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);
	 }

     Compile and run:

	 % cc -o power power.c `perl -MExtUtils::Embed -e ccopts -e ldopts`

	 % power
	 3 to the 4th power is 81.


     Maintaining a persistent interpreter    [Toc]    [Back]

     When developing interactive and/or	potentially long-running applications,
     it's a good idea to maintain a persistent interpreter rather than
     allocating	and constructing a new interpreter multiple times.  The	major
     reason is speed: since Perl will only be loaded into memory once.






								       Page 12






PERLEMBED(1)							  PERLEMBED(1)



     However, you have to be more cautious with	namespace and variable scoping
     when using	a persistent interpreter.  In previous examples	we've been
     using global variables in the default package main.  We knew exactly what
     code would	be run,	and assumed we could avoid variable collisions and
     outrageous	symbol table growth.

     Let's say your application	is a server that will occasionally run Perl
     code from some arbitrary file.  Your server has no	way of knowing what
     code it's going to	run.  Very dangerous.

     If	the file is pulled in by perl_parse(), compiled	into a newly
     constructed interpreter, and subsequently cleaned out with
     perl_destruct() afterwards, you're	shielded from most namespace troubles.

     One way to	avoid namespace	collisions in this scenario is to translate
     the filename into a guaranteed-unique package name, and then compile the
     code into that package using the eval entry in the	perlfunc manpage.  In
     the example below,	each file will only be compiled	once.  Or, the
     application might choose to clean out the symbol table associated with
     the file after it's no longer needed.  Using the perl_call_argv entry in
     the perlcall manpage, We'll call the subroutine
     Embed::Persistent::eval_file which	lives in the file persistent.pl	and
     pass the filename and boolean cleanup/cache flag as arguments.

     Note that the process will	continue to grow for each file that it uses.
     In	addition, there	might be AUTOLOADed subroutines	and other conditions
     that cause	Perl's symbol table to grow.  You might	want to	add some logic
     that keeps	track of the process size, or restarts itself after a certain
     number of requests, to ensure that	memory consumption is minimized.
     You'll also want to scope your variables with the my entry	in the
     perlfunc manpage whenever possible.

      package Embed::Persistent;
      #persistent.pl

      use strict;
      use vars '%Cache';

      sub valid_package_name {
	  my($string) =	@_;
	  $string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg;
	  # second pass	only for words starting	with a digit
	  $string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg;

	  # Dress it up	as a real package name
	  $string =~ s|/|::|g;
	  return "Embed" . $string;
      }







								       Page 13






PERLEMBED(1)							  PERLEMBED(1)



      #borrowed	from Safe.pm
      sub delete_package {
	  my $pkg = shift;
	  my ($stem, $leaf);

	  no strict 'refs';
	  $pkg = "main::$pkg\::";    # expand to full symbol table name
	  ($stem, $leaf) = $pkg	=~ m/(.*::)(\w+::)$/;

	  my $stem_symtab = *{$stem}{HASH};

	  delete $stem_symtab->{$leaf};
      }

      sub eval_file {
	  my($filename,	$delete) = @_;
	  my $package =	valid_package_name($filename);
	  my $mtime = -M $filename;
	  if(defined $Cache{$package}{mtime}
	     &&
	     $Cache{$package}{mtime} <=	$mtime)
	  {
	     # we have compiled	this subroutine	already,
	     # it has not been updated on disk,	nothing	left to	do
	     print STDERR "already compiled $package->handler\n";
	  }
	  else {
	     local *FH;
	     open FH, $filename	or die "open '$filename' $!";
	     local($/) = undef;
	     my	$sub = <FH>;
	     close FH;

	     #wrap the code into a subroutine inside our unique	package
	     my	$eval =	qq{package $package; sub handler { $sub; }};
	     {
		 # hide	our variables within this block
		 my($filename,$mtime,$package,$sub);
		 eval $eval;
	     }
	     die $@ if $@;

	     #cache it unless we're cleaning out each time
	     $Cache{$package}{mtime} = $mtime unless $delete;
	  }

	  eval {$package->handler;};
	  die $@ if $@;

	  delete_package($package) if $delete;





								       Page 14






PERLEMBED(1)							  PERLEMBED(1)



	  #take	a look if you want
	  #print Devel::Symdump->rnew($package)->as_string, $/;
      }

      1;

      __END__

      /* persistent.c */
      #include <EXTERN.h>
      #include <perl.h>

      /* 1 = clean out filename's symbol table after each request, 0 = don't */
      #ifndef DO_CLEAN
      #define DO_CLEAN 0
      #endif

      static PerlInterpreter *perl = NULL;

      int
      main(int argc, char **argv, char **env)
      {
	  char *embedding[] = {	"", "persistent.pl" };
	  char *args[] = { "", DO_CLEAN, NULL };
	  char filename	[1024];
	  int exitstatus = 0;

	  if((perl = perl_alloc()) == NULL) {
	     fprintf(stderr, "no memory!");
	     exit(1);
	  }
	  perl_construct(perl);

	  exitstatus = perl_parse(perl,	NULL, 2, embedding, NULL);

	  if(!exitstatus) {
	     exitstatus	= perl_run(perl);

	     while(printf("Enter file name: ") && gets(filename)) {

		 /* call the subroutine, passing it the	filename as an argument	*/
		 args[0] = filename;
		 perl_call_argv("Embed::Persistent::eval_file",
				G_DISCARD | G_EVAL, args);

		 /* check $@ */
		 if(SvTRUE(GvSV(errgv)))
		     fprintf(stderr, "eval error: %s\n", SvPV(GvSV(errgv),na));
	     }
	  }





								       Page 15






PERLEMBED(1)							  PERLEMBED(1)



	  perl_destruct_level =	0;
	  perl_destruct(perl);
	  perl_free(perl);
	  exit(exitstatus);
      }

     Now compile:

      %	cc -o persistent persistent.c `perl -MExtUtils::Embed -e ccopts	-e ldopts`

     Here's a example script file:

      #test.pl
      my $string = "hello";
      foo($string);

      sub foo {
	  print	"foo says: @_\n";
      }

     Now run:

      %	persistent
      Enter file name: test.pl
      foo says:	hello
      Enter file name: test.pl
      already compiled Embed::test_2epl->handler
      foo says:	hello
      Enter file name: ^C


     Maintaining multiple interpreter instances    [Toc]    [Back]

     Some rare applications will need to create	more than one interpreter
     during a session.	Such an	application might sporadically decide to
     release any resources associated with the interpreter.

     The program must take care	to ensure that this takes place	before the
     next interpreter is constructed.  By default, the global variable
     perl_destruct_level is set	to 0, since extra cleaning isn't needed	when a
     program has only one interpreter.

     Setting perl_destruct_level to 1 makes everything squeaky clean:

      perl_destruct_level = 1;










								       Page 16






PERLEMBED(1)							  PERLEMBED(1)



      while(1) {
	  ...
	  /* reset global variables here with perl_destruct_level = 1 */
	  perl_construct(my_perl);
	  ...
	  /* clean and reset _everything_ during perl_destruct */
	  perl_destruct(my_perl);
	  perl_free(my_perl);
	  ...
	  /* let's go do it again! */
      }

     When perl_destruct() is called, the interpreter's syntax parse tree and
     symbol tables are cleaned up, and global variables	are reset.

     Now suppose we have more than one interpreter instance running at the
     same time.	 This is feasible, but only if you used	the -DMULTIPLICITY
     flag when building	Perl.  By default, that	sets perl_destruct_level to 1.

     Let's give	it a try:

      #include <EXTERN.h>
      #include <perl.h>

      /* we're going to	embed two interpreters */
      /* we're going to	embed two interpreters */

      #define SAY_HELLO	"-e", "print qq(Hi, I'm	$^X\n)"

      int main(int argc, char **argv, char **env)
      {
	  PerlInterpreter
	      *one_perl	= perl_alloc(),
	      *two_perl	= perl_alloc();
	  char *one_args[] = { "one_perl", SAY_HELLO };
	  char *two_args[] = { "two_perl", SAY_HELLO };

	  perl_construct(one_perl);
	  perl_construct(two_perl);

	  perl_parse(one_perl, NULL, 3,	one_args, (char	**)NULL);
	  perl_parse(two_perl, NULL, 3,	two_args, (char	**)NULL);

	  perl_run(one_perl);
	  perl_run(two_perl);

	  perl_destruct(one_perl);
	  perl_destruct(two_perl);

	  perl_free(one_perl);
	  perl_free(two_perl);
      }



								       Page 17






PERLEMBED(1)							  PERLEMBED(1)



     Compile as	usual:

      %	cc -o multiplicity multiplicity.c `perl	-MExtUtils::Embed -e ccopts -e ldopts`

     Run it, Run it:

      %	multiplicity
      Hi, I'm one_perl
      Hi, I'm two_perl


     Using Perl	modules, which themselves use C	libraries, from	your C program

     If	you've played with the examples	above and tried	to embed a script that
     use()s a Perl module (such	as Socket) which itself	uses a C or C++
     library, this probably happened:

      Can't load module	Socket,	dynamic	loading	not available in this perl.
       (You may	need to	build a	new perl executable which either supports
       dynamic loading or has the Socket module	statically linked into it.)

     What's wrong?

     Your interpreter doesn't know how to communicate with these extensions on
     its own.  A little	glue will help.	 Up until now you've been calling
     perl_parse(), handing it NULL for the second argument:

      perl_parse(my_perl, NULL,	argc, my_argv, NULL);

     That's where the glue code	can be inserted	to create the initial contact
     between Perl and linked C/C++ routines.  Let's take a look	some pieces of
     perlmain.c	to see how Perl	does this:

      #ifdef __cplusplus
      #	 define	EXTERN_C extern	"C"
      #else
      #	 define	EXTERN_C extern
      #endif

      static void xs_init _((void));

      EXTERN_C void boot_DynaLoader _((CV* cv));
      EXTERN_C void boot_Socket	_((CV* cv));

      EXTERN_C void
      xs_init()
      {
	     char *file	= __FILE__;
	     /*	DynaLoader is a	special	case */
	     newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
	     newXS("Socket::bootstrap",	boot_Socket, file);
      }



								       Page 18






PERLEMBED(1)							  PERLEMBED(1)



     Simply put: for each extension linked with	your Perl executable
     (determined during	its initial configuration on your computer or when
     adding a new extension), a	Perl subroutine	is created to incorporate the
     extension's routines.  Normally, that subroutine is named
     Module::bootstrap() and is	invoked	when you say use Module.  In turn,
     this hooks	into an	XSUB, boot_Module, which creates a Perl	counterpart
     for each of the extension's XSUBs.	 Don't worry about this	part; leave
     that to the xsubpp	and extension authors.	If your	extension is
     dynamically loaded, DynaLoader creates Module::bootstrap()	for you	on the
     fly.  In fact, if you have	a working DynaLoader then there	is rarely any
     need to link in any other extensions statically.

     Once you have this	code, slap it into the second argument of
     perl_parse():

      perl_parse(my_perl, xs_init, argc, my_argv, NULL);

     Then compile:

      %	cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts	-e ldopts`

      %	interp
	use Socket;
	use SomeDynamicallyLoadedModule;

	print "Now I can use extensions!\n"'

     ExtUtils::Embed can also automate writing the xs_init glue	code.

      %	perl -MExtUtils::Embed -e xsinit -- -o perlxsi.c
      %	cc -c perlxsi.c	`perl -MExtUtils::Embed	-e ccopts`
      %	cc -c interp.c	`perl -MExtUtils::Embed	-e ccopts`
      %	cc -o interp perlxsi.o interp.o	`perl -MExtUtils::Embed	-e ldopts`

     Consult the perlxs	manpage	and the	perlguts manpage for more details.

Embedding Perl under Win32    [Toc]    [Back]

     At	the time of this writing, there	are two	versions of Perl which run
     under Win32.  Interfacing to Activeware's Perl library is quite different
     from the examples in this documentation, as significant changes were made
     to	the internal Perl API.	However, it is possible	to embed Activeware's
     Perl runtime, see the Perl	for Win32 FAQ:
     http://www.perl.com/perl/faq/win32/Perl_for_Win32_FAQ.html

     With the "official" Perl version 5.004 or higher, all the examples	within
     this documentation	will compile and run untouched,	although, the build
     process is	slightly different between Unix	and Win32.

     For starters, backticks don't work	under the Win32	native command shell!
     The ExtUtils::Embed kit on	CPAN ships with	a script called	genmake, which
     generates a simple	makefile to build a program from a single C source
     file.  It can be used like	so:



								       Page 19






PERLEMBED(1)							  PERLEMBED(1)



      C:\ExtUtils-Embed\eg> perl genmake interp.c
      C:\ExtUtils-Embed\eg> nmake
      C:\ExtUtils-Embed\eg> interp -e "print qq{I'm embedded in	Win32!\n}"

     You may wish to use a more	robust environment such	as the MS Developer
     stdio.  In	this case, to generate perlxsi.c run:

      perl -MExtUtils::Embed -e	xsinit

     Create a new project, Insert -> Files into	Project: perlxsi.c, perl.lib,
     and your own source files,	e.g. interp.c.	Typically you'll find perl.lib
     in	C:\perl\lib\CORE, if not, you should see the CORE directory relative
     to	perl -V:archlib.  The studio will also need this path so it knows
     where to find Perl	include	files.	This path can be added via the Tools
     ->	Options	-> Directories menu.  Finnally,	select Build ->	Build
     interp.exe	and you're ready to go!

MORAL    [Toc]    [Back]

     You can sometimes write faster code in C, but you can always write	code
     faster in Perl.  Because you can use each from the	other, combine them as
     you wish.

AUTHOR    [Toc]    [Back]

     Jon Orwant	and <orwant@tpj.com> and Doug MacEachern <dougm@osf.org>, with
     small contributions from Tim Bunce, Tom Christiansen, Hallvard Furuseth,
     Dov Grobgeld, and Ilya Zakharevich.

     Check out Doug's article on embedding in Volume 1,	Issue 4	of The Perl
     Journal.  Info about TPJ is available from	http://tpj.com.

     July 17, 1997

     Some of this material is excerpted	from Jon Orwant's book:	Perl 5
     Interactive, Waite	Group Press, 1996 (ISBN	1-57169-064-6) and appears
     courtesy of Waite Group Press.

COPYRIGHT    [Toc]    [Back]

     Copyright (C) 1995, 1996, 1997 Doug MacEachern and	Jon Orwant.  All
     Rights Reserved.

     Although destined for release with	the standard Perl distribution,	this
     document is not public domain, nor	is any of Perl and its documentation.
     Permission	is granted to freely distribute	verbatim copies	of this
     document provided that no modifications outside of	formatting be made,
     and that this notice remain intact.  You are permitted and	encouraged to
     use its code and derivatives thereof in your own source code for fun or
     for profit	as you see fit.








								       Page 20






PERLEMBED(1)							  PERLEMBED(1)


								       PPPPaaaaggggeeee 22221111
[ Back ]
 Similar pages
Name OS Title
perljp OpenBSD AEuEU,i Perl Y~YxYE `A^a`I`A Perl xIAx3|xOxex|x3x1/2! Perl 5.8.0 xexeicUni- _ codeYuYYi1/4YEx~AcEyxE...
diagnostics IRIX Perl compiler pragma to force verbose warning diagnostics splain - standalone program to do the same thing
setmemwindow HP-UX changes the window id of a running program or starts a program in a particular memory window
perl584delta OpenBSD what is new for perl v5.8.4
perl585delta OpenBSD what is new for perl v5.8.5
perl581delta OpenBSD what is new for perl v5.8.1
perl58delta OpenBSD what is new for perl v5.8.0
perl583delta OpenBSD what is new for perl v5.8.3
perl582delta OpenBSD what is new for perl v5.8.2
perl56delta OpenBSD what's new for perl v5.6.0
Copyright © 2004-2005 DeniX Solutions SRL
newsletter delivery service