diff options
author | Perl 5 Porters <perl5-porters@africa.nicoh.com> | 1997-01-04 17:44:00 +1200 |
---|---|---|
committer | Chip Salzenberg <chip@atlantic.net> | 1997-01-04 17:44:00 +1200 |
commit | 8ebc5c0145d2e3559bce3073437e6d027dcdffcc (patch) | |
tree | 19e91b8b9e9b19b4116b7b4b64f2a4755e6bd179 /pod/perlembed.pod | |
parent | 7cfe7857715f78206e6d7d6f7fd52983de4dec44 (diff) | |
download | perl-8ebc5c0145d2e3559bce3073437e6d027dcdffcc.tar.gz |
[inseparable changes from patch from perl5.003_18 to perl5.003_19]
CORE LANGUAGE CHANGES
Subject: Make method cache invisible to user code
From: Chip Salzenberg <chip@atlantic.net>
Files: dump.c gv.c gv.h hv.c op.c perl.c pp_hot.c pp_sys.c sv.c toke.c
Subject: Never parse "{m,s,y,tr,q{,q,w,x}}:{,:}" as package or label
From: Chip Salzenberg <chip@atlantic.net>
Files: toke.c
CORE PORTABILITY
Subject: Fix $^X under HP-UX
From: Chip Salzenberg <chip@atlantic.net>
Files: hints/hpux.sh toke.c
Subject: New hints/hpux.sh
Date: Tue, 31 Dec 1996 15:09:32 -0800
From: Jeff Okamoto <okamoto@hpcc123.corp.hp.com>
Files: hints/hpux.sh
private-msgid: <199612312309.AA283393772@hpcc123.corp.hp.com>
DOCUMENTATION
Subject: Perlguts, version 28
Date: Fri, 3 Jan 1997 13:10:46 -0800
From: Jeff Okamoto <okamoto@hpcc123.corp.hp.com>
Files: pod/perlguts.pod
private-msgid: <199701032110.AA102535846@hpcc123.corp.hp.com>
Subject: Miscellaneous pod patches
From: Ralf S. Engelschall <rse@engelschall.com>
Files: pod/Makefile pod/perldebug.pod pod/perlfunc.pod pod/perlguts.pod
Subject: expanded flock() docs
Date: Fri, 03 Jan 1997 19:31:11 -0500
From: Roderick Schertler <roderick@gate.net>
Files: pod/perlfunc.pod
Msg-ID: <4481.852337871@eeyore.ibcinc.com>
(applied based on p5p patch as commit 1fd81fbbe87d964ad1f7dbdce41e36f3781dcf82)
Subject: Use Text::Wrap in buildtoc; run buildtoc
From: Ulrich Pfeifer <pfeifer@charly.informatik.uni-dortmund.de>
Files: pod/buildtoc pod/perltoc.pod
Subject: Remove obsolete perlovl.pod
From: Chip Salzenberg <chip@atlantic.net>
Files: MANIFEST plan9/mkfile pod/perlovl.pod vms/Makefile vms/descrip.mms
OTHER CORE CHANGES
Subject: Fix segv when calling named closures
From: Chip Salzenberg <chip@atlantic.net>
Files: pp_hot.c
Subject: Finish rationalizing "undef value" warnings
From: Chip Salzenberg <chip@atlantic.net>
Files: doop.c pp.c sv.c t/op/assignwarn.t
Subject: Arrange for all "_<file" entries to be in %main::
From: Chip Salzenberg <chip@atlantic.net>
Files: gv.c lib/perl5db.pl
Subject: Introduce CVf_NODEBUG flag
Date: Wed, 01 Jan 1997 15:42:05 -0500
From: Gurusamy Sarathy <gsar@engin.umich.edu>
Files: cv.h pp_hot.c
Msg-ID: <199701012042.PAA25994@aatma.engin.umich.edu>
(applied based on p5p patch as commit a3d90dd510fe5a67ed9b80e603493d285c30aa97)
Subject: Reword 'may be "0"' warning per Larry; fix its line number
From: Chip Salzenberg <chip@atlantic.net>
Files: op.c pod/perldiag.pod
Subject: 5.003_18: perl_{con,des}truct fixes
Date: Fri, 03 Jan 1997 15:42:04 -0500
From: Doug MacEachern <dougm@osf.org>
Files: perl.c perl.h pod/perlembed.pod pod/perltoc.pod t/op/sysio.t
Msg-ID: <199701032042.PAA06766@postman.osf.org>
(applied based on p5p patch as commit 316c7b3d7b47e3143f94c7f8621e854c519d1e87)
Subject: Fix lost value from READLINE after TIEHANDLE
From: Gurusamy Sarathy <gsar@engin.umich.edu>
Files: pp_hot.c sv.h
TESTS
Subject: Create t/pragma directory; populate with new and old
From: Paul Marquess <pmarquess@bfsec.bt.co.uk>
Files: MANIFEST Makefile.SH t/TEST t/comp/use.t t/lib/locale.t t/op/overload.t t/op/use.t t/pragma/locale.t t/pragma/overload.t t/pragma/strict-refs t/pragma/strict-subs t/pragma/strict-vars t/pragma/strict.t t/pragma/subs.t t/pragma/warn-global t/pragma/warning.t
Subject: New tests: comp/colon.t and op/assignwarn.t
From: Robin Barker <rmb@cise.npl.co.uk>
Files: MANIFEST t/comp/colon.t t/op/assignwarn.t
Diffstat (limited to 'pod/perlembed.pod')
-rw-r--r-- | pod/perlembed.pod | 215 |
1 files changed, 162 insertions, 53 deletions
diff --git a/pod/perlembed.pod b/pod/perlembed.pod index 30c6e0a0a7..e55ee633c9 100644 --- a/pod/perlembed.pod +++ b/pod/perlembed.pod @@ -51,6 +51,8 @@ L<Fiddling with the Perl stack from your C program> L<Maintaining a persistent interpreter> +L<Maintaining multiple interpreter instances> + L<Using Perl modules, which themselves use C libraries, from your C program> This documentation is UNIX specific. @@ -126,7 +128,6 @@ In a sense, perl (the C program) is a good example of embedding Perl from the source distribution. Here's a bastardized, non-portable 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 */ @@ -173,12 +174,12 @@ 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 call to I<perl_call_argv()>. +To call individual Perl subroutines, you can use any of the B<perl_call_*> +functions documented in the L<perlcall> man page. +In this example we'll use 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> @@ -186,13 +187,16 @@ That's shown below, in a program I'll call I<showtime.c>. 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); - /*** This replaces perl_run() ***/ - perl_call_argv("showtime", G_DISCARD | G_NOARGS, argv); + /*** skipping perl_run() ***/ + + perl_call_argv("showtime", G_DISCARD | G_NOARGS, args); + perl_destruct(my_perl); perl_free(my_perl); } @@ -220,8 +224,15 @@ 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 +Note that in this particular case we are not required to call I<perl_run>, +however, in general it's considered good practice to ensure proper +initialization of library code including execution of all object C<DESTROY> +methods and package C<END {}> blocks. + +If you want to pass some arguments to the Perl subroutine, you may add +strings to the C<NULL> terminated C<args> list passed to I<perl_call_argv>. +In order to pass arguments of another data type and/or examine return values +of the subroutine you'll need to manipulate the Perl stack, demonstrated in the last section of this document: L<Fiddling with the Perl stack from your C program> @@ -235,15 +246,14 @@ flag to L<perlguts/perl_eval_sv>. Arguably, this is the only routine you'll ever need to execute snippets of Perl code from within your C program. Your string can be as long as you wish; it can contain multiple statements; it can -use L<perlfunc/require> or L<perlfunc/do> to include external Perl -files. +include L<perlfunc/use>, L<perlfunc/require> and L<perlfunc/do> to +include external Perl files. Our I<perl_eval()> lets us evaluate individual Perl strings, and then extract variables for coercion into C types. The following program, I<string.c>, executes three Perl strings, extracting an C<int> from the first, a C<float> from the second, and a C<char *> from the third. - #include <stdio.h> #include <EXTERN.h> #include <perl.h> @@ -263,7 +273,7 @@ the first, a C<float> from the second, and a C<char *> from the third. perl_construct( my_perl ); perl_parse(my_perl, NULL, 3, embedding, NULL); - + perl_run(my_perl); /** Treat $a as an integer **/ perl_eval("$a = 3; $a **= 2"); printf("a = %d\n", SvIV(perl_get_sv("a", FALSE))); @@ -320,7 +330,6 @@ returning the number of matches found. Here's a sample program, I<match.c>, that uses all three (long lines have been wrapped here): - #include <stdio.h> #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; @@ -339,7 +348,7 @@ been wrapped here): char *command; command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 37); sprintf(command, "$string = '%s'; $return = $string =~ %s", - string, pattern); + string, pattern); perl_eval(command); free(command); return SvIV(perl_get_sv("return", FALSE)); @@ -357,11 +366,11 @@ been wrapped here): STRLEN length; command = malloc(sizeof(char) * strlen(*string) + strlen(pattern) + 35); sprintf(command, "$string = '%s'; $ret = ($string =~ %s)", - *string, pattern); - perl_eval(command); - free(command); - *string = SvPV(perl_get_sv("string", FALSE), length); - return SvIV(perl_get_sv("ret", FALSE)); + *string, pattern); + perl_eval(command); + free(command); + *string = SvPV(perl_get_sv("string", FALSE), length); + return SvIV(perl_get_sv("ret", FALSE)); } /** matches(string, pattern, matches) ** @@ -380,7 +389,7 @@ been wrapped here): int i; command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 38); sprintf(command, "$string = '%s'; @array = ($string =~ %s)", - string, pattern); + string, pattern); perl_eval(command); free(command); array = perl_get_av("array", FALSE); @@ -401,6 +410,8 @@ been wrapped here): my_perl = perl_alloc(); perl_construct( my_perl ); perl_parse(my_perl, NULL, 3, embedding, NULL); + perl_run(my_perl); + text = (char *) malloc(sizeof(char) * 486); /** A long string follows! **/ sprintf(text, "%s", "When he is at a convenience store and the bill \ comes to some amount like 76 cents, Maynard is aware that there is \ @@ -432,7 +443,7 @@ been wrapped here): num_matches = substitute(&text, "s/[aeiou]//gi"); if (num_matches) { printf("substitute: s/[aeiou]//gi...%d substitutions made.\n", - num_matches); + num_matches); printf("Now text is: %s\n\n", text); } /** Attempt a substitution **/ @@ -496,7 +507,6 @@ 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> @@ -532,6 +542,7 @@ deep breath... sprintf(my_argv[1], "power.pl"); perl_parse(my_perl, NULL, argc, my_argv, NULL); + perl_run(my_perl); PerlPower(3, 4); /*** Compute 3 ** 4 ***/ @@ -613,7 +624,7 @@ reduce symbol table growth. my ($stem, $leaf); no strict 'refs'; - $pkg = "main::$pkg\::"; # expand to full symbol table name + $pkg = "main::$pkg\::"; # expand to full symbol table name ($stem, $leaf) = $pkg =~ m/(.*::)(\w+::)$/; my $stem_symtab = *{$stem}{HASH}; @@ -629,28 +640,28 @@ reduce symbol table growth. && $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"; + # 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; + 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($r,$filename,$mtime,$package,$sub); - eval $eval; - } - die $@ if $@; + #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; + #cache it unless we're cleaning out each time + $Cache{$package}{mtime} = $mtime unless $delete; } eval {$package->handler;}; @@ -686,27 +697,27 @@ reduce symbol table growth. int exitstatus = 0; if((perl = perl_alloc()) == NULL) { - fprintf(stderr, "no memory!"); - exit(1); + fprintf(stderr, "no memory!"); + exit(1); } perl_construct(perl); exitstatus = perl_parse(perl, NULL, 2, embedding, NULL); if(!exitstatus) { - exitstatus = perl_run(perl); + exitstatus = perl_run(perl); - while(printf("Enter file name: ") && gets(filename)) { + 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); + /* 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)); - } + /* check $@ */ + if(SvTRUE(GvSV(errgv))) + fprintf(stderr, "eval error: %s\n", SvPV(GvSV(errgv),na)); + } } perl_destruct_level = 0; @@ -740,6 +751,104 @@ Now run: foo says: hello Enter file name: ^C +=head2 Maintaining multiple interpreter instances + +The previous examples have gone through several steps to startup, use and +shutdown an embedded Perl interpreter. Certain applications may require +more than one instance of an interpreter to be created during the lifespan +of a single process. Such an application may take different approaches in +it's use of interpreter objects. For example, a particular transaction may +want to create an interpreter instance, then release any resources associated +with the object once the transaction is completed. When a single process +does this once, resources are released upon exit of the program and the next +time it starts, the interpreter's global state is fresh. + +In the same process, the program must take care to ensure that these +actions take place before constructing a new interpreter. By default, the +global variable C<perl_destruct_level> is set to C<0> since extra cleaning +is not needed when a program constructs a single interpreter, such as the +perl executable itself in C</usr/bin/perl> or some such. + +You can tell Perl to make everything squeeky clean by setting +C<perl_destruct_level> to C<1>. + + perl_destruct_level = 1; /* perl global variable */ + while(1) { + ... + /* reset global variables here with perl_destruct_level = 1 */ + perl_contruct(my_perl); + ... + /* clean and reset _everything_ during perl_destruct */ + perl_destruct(my_perl); /* ah, nice and fresh */ + perl_free(my_perl); + ... + /* let's go do it again! */ + } + +Now, when I<perl_destruct()> is called, the interpreter's syntax parsetree +and symbol tables are cleaned out, along with reseting global variables. + +So, we've seen how to startup and shutdown an interpreter more than once +in the same process, but there was only one instance in existance at any +one time. Hmm, wonder if we can have more than one interpreter instance +running at the _same_ time? +Indeed this is possible, however when you build Perl, you must compile with +C<-DMULTIPLICITY>. + +It's a little tricky for the Perl runtime to handle multiple interpreters, +introducing some overhead that most programs with a single interpreter don't +get burdened with. When you compile with C<-DMULTIPLICITY>, by default, +C<perl_destruct_level> is set to C<1> for each interpreter. + +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); + } + + +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 + =head2 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 |