X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlembed.pod;h=79783a7d30d651f412aada12d751fa33d53c7bb3;hb=1b3f7d2103791ceee4a17b0f9f5860baa1512c7a;hp=646cd670a19daea85d0d1bfec5ece25d7a6267c3;hpb=96dbc785049371b8845893bf40bd39d4db026518;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlembed.pod b/pod/perlembed.pod index 646cd67..79783a7 100644 --- a/pod/perlembed.pod +++ b/pod/perlembed.pod @@ -14,14 +14,14 @@ Do you want to: Read L and L. -=item B +=item B -Read about backquotes and L and L. +Read about back-quotes and about C and C in L. =item B -Read about L and L and L -and L. +Read about L and L and L +and L. =item B @@ -37,7 +37,7 @@ Read on... L -There's one example in each of the six sections: +There's one example in each of the eight sections: L @@ -49,14 +49,22 @@ L L +L + +L + L -This documentation is UNIX specific. +This documentation is Unix specific; if you have information about how +to embed Perl on other platforms, please send e-mail to >. =head2 Compiling your C program -Every C program that uses Perl must link in the I. +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 I. 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 or equivalent). (Corollary: you @@ -65,13 +73,14 @@ your machine, or installed properly--that's why you shouldn't blithely copy Perl executables from machine to machine without also copying the I directory.) -Your C program will--usually--allocate, "run", and deallocate a -I object, which is defined in the perl library. +When you use Perl from C, your C program will--usually--allocate, +"run", and deallocate a I object, which is defined by +the perl library. If your copy of Perl is recent enough to contain this documentation -(5.002 or later), then the perl library (and I and -I, which you'll also need) will -reside in a directory resembling this: +(version 5.002 or later), then the perl library (and I and +I, which you'll also need) will reside in a directory +that looks like this: /usr/local/lib/perl5/your_architecture_here/CORE @@ -87,44 +96,65 @@ Execute this statement for a hint about where to find CORE: perl -MConfig -e 'print $Config{archlib}' -Here's how you might compile the example in the next section, -L, -on a DEC Alpha running the OSF operating system: +Here's how you'd compile the example in the next section, +L, 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: - % 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 + % 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 -You'll have to choose the appropriate compiler (I, I, et al.) and -library directory (I) 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 I or I, you need -to change the path following the -I. +How can you figure out what to add? Assuming your Perl is post-5.001, +execute a C command and pay special attention to the "cc" and +"ccflags" information. + +You'll have to choose the appropriate compiler (I, I, et al.) for +your machine: C will tell you what +to use. + +You'll also have to choose the appropriate library directory +(I) 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 C<-L>. If it +complains that it can't find I and I, you need to +change the path following the C<-I>. You may have to add extra libraries as well. Which ones? Perhaps those printed by perl -MConfig -e 'print $Config{libs}' -We strongly recommend you use the B module to determine -all of this information for you: +Provided your perl binary was properly configured and installed the +B module will determine all of this information for +you: % cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts` +If the B 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.) -If the B module is not part of your perl kit's -distribution you can retrieve it from: -http://www.perl.com/cgi-bin/cpan_mod?module=ExtUtils::Embed. - +The B kit on CPAN also contains all source code for +the examples in this document, tests, additional examples and other +information you may find useful. =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, -from the source distribution. Here's a bastardized, non-portable version of -I containing the essentials of embedding: +from the source distribution. Here's a bastardized, nonportable +version of I containing the essentials of embedding: - #include #include /* from the Perl distribution */ #include /* from the Perl distribution */ @@ -140,11 +170,9 @@ I containing the essentials of embedding: perl_free(my_perl); } -Note that we do not use the C pointer here or in any of the -following examples. -Normally handed to C as it's final argument, -we hand it a B instead, in which case the current environment -is used. +Notice that we don't use the C pointer. Normally handed to +C as its final argument, C here is replaced by +C, which means that the current environment will be used. Now compile this program (I'll call it I) into an executable: @@ -171,12 +199,12 @@ calling I. =head2 Calling a Perl subroutine from your C program -To call individual Perl subroutines, you'll need to remove the call to -I and replace it with a call to I. +To call individual Perl subroutines, you can use any of the B +functions documented in the L manpage. +In this example we'll use I. That's shown below, in a program I'll call I. - #include #include #include @@ -184,13 +212,16 @@ That's shown below, in a program I'll call I. 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); } @@ -215,73 +246,66 @@ Simple enough. Now compile and run: 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 +(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, demonstrated in the last section of this document: -L +In this particular case we don't have to call I, but in +general it's considered good practice to ensure proper initialization +of library code, including execution of all object C methods +and package C blocks. -=head2 Evaluating a Perl statement from your C program +If you want to pass arguments to the Perl subroutine, you can add +strings to the C-terminated C list passed to +I. 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: L. -NOTE: This section, and the next, employ some very brittle techniques -for evaluting strings of Perl code. Perl 5.002 contains some nifty -features that enable A Better Way (such as with L). -Look for updates to this document soon. +=head2 Evaluating a Perl statement from your C program -One way to evaluate a Perl string is to define a function (we'll call -ours I) that wraps around Perl's L. +Perl provides two API functions to evaluate pieces of Perl code. +These are L and L. -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 or L to include external Perl -files. +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 +L, L and L to include +external Perl files. -Our I lets us evaluate individual Perl strings, and then +I lets us evaluate individual Perl strings, and then extract variables for coercion into C types. The following program, I, executes three Perl strings, extracting an C from the first, a C from the second, and a C from the third. - #include #include #include - + static PerlInterpreter *my_perl; - - int perl_eval(char *string) - { - char *argv[2]; - argv[0] = string; - argv[1] = NULL; - perl_call_argv("_eval_", 0, argv); - } - + main (int argc, char **argv, char **env) { - char *embedding[] = { "", "-e", "sub _eval_ { eval $_[0] }" }; - STRLEN length; - - my_perl = perl_alloc(); - perl_construct( my_perl ); - - perl_parse(my_perl, NULL, 3, embedding, NULL); - - /** Treat $a as an integer **/ - perl_eval("$a = 3; $a **= 2"); - printf("a = %d\n", SvIV(perl_get_sv("a", FALSE))); - - /** Treat $a as a float **/ - perl_eval("$a = 3.14; $a **= 2"); - printf("a = %f\n", SvNV(perl_get_sv("a", FALSE))); - - /** Treat $a as a string **/ - perl_eval("$a = 'rekcaH lreP rehtonA tsuJ'; $a = reverse($a); "); - printf("a = %s\n", SvPV(perl_get_sv("a", FALSE), length)); - - perl_destruct(my_perl); - perl_free(my_perl); + 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 I in their names help convert Perl scalars to C types. They're described in L. @@ -294,47 +318,53 @@ I to create a string: 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 L 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. =head2 Performing Perl pattern matches and substitutions from your C program -Our I lets us evaluate strings of Perl code, so we can +The I function lets us evaluate strings of Perl code, so we can define some functions that use it to "specialize" in matches and substitutions: I, I, and I. char match(char *string, char *pattern); -Given a string and a pattern (e.g. "m/clasp/" or "/\b\w*\b/", which in -your program might be represented as C<"/\\b\\w*\\b/">), +Given a string and a pattern (e.g., C or C, 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(char *string[], char *pattern); -Given a pointer to a string and an "=~" operation (e.g. "s/bob/robert/g" or -"tr[A-Z][a-z]"), modifies the string according to the operation, -returning the number of substitutions made. +Given a pointer to a string and an C<=~> operation (e.g., +C or C), substitute() modifies the string +according to the operation, returning the number of substitutions +made. int matches(char *string, char *pattern, char **matches[]); Given a string, a pattern, and a pointer to an empty array of strings, -evaluates C<$string =~ $pattern> in an array context, and fills in -I with the array elements (allocating memory as it does so), -returning the number of matches found. +matches() evaluates C<$string =~ $pattern> in an array context, and +fills in I with the array elements (allocating memory as it +does so), returning the number of matches found. Here's a sample program, I, that uses all three (long lines have been wrapped here): - #include #include #include + static PerlInterpreter *my_perl; - int perl_eval(char *string) - { - char *argv[2]; - argv[0] = string; - argv[1] = NULL; - perl_call_argv("_eval_", 0, argv); - } + /** match(string, pattern) ** ** Used for matches in a scalar context. @@ -346,8 +376,8 @@ been wrapped here): char *command; command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 37); sprintf(command, "$string = '%s'; $return = $string =~ %s", - string, pattern); - perl_eval(command); + string, pattern); + perl_eval_pv(command, TRUE); free(command); return SvIV(perl_get_sv("return", FALSE)); } @@ -364,11 +394,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_pv(command, TRUE); + free(command); + *string = SvPV(perl_get_sv("string", FALSE), length); + return SvIV(perl_get_sv("ret", FALSE)); } /** matches(string, pattern, matches) ** @@ -387,8 +417,8 @@ been wrapped here): int i; command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 38); sprintf(command, "$string = '%s'; @array = ($string =~ %s)", - string, pattern); - perl_eval(command); + string, pattern); + perl_eval_pv(command, TRUE); free(command); array = perl_get_av("array", FALSE); num_matches = av_len(array) + 1; /** assume $[ is 0 **/ @@ -401,13 +431,15 @@ been wrapped here): } main (int argc, char **argv, char **env) { - char *embedding[] = { "", "-e", "sub _eval_ { eval $_[0] }" }; + char *embedding[] = { "", "-e", "0" }; char *text, **match_list; int num_matches, i; int j; 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 \ @@ -439,7 +471,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 **/ @@ -453,22 +485,22 @@ been wrapped here): which produces the output (again, long lines have been wrapped here) - perl_match: Text contains the word 'quarter'. + match: Text contains the word 'quarter'. - perl_match: Text doesn't contain the word 'eighth'. + match: Text doesn't contain the word 'eighth'. - perl_matches: m/(wi..)/g found 2 matches... + matches: m/(wi..)/g found 2 matches... match: will match: with - perl_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, + 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 - perl_substitute: s/Perl/C...No substitution made. + substitute: s/Perl/C...No substitution made. =head2 Fiddling with the Perl stack from your C program @@ -488,9 +520,9 @@ described in L. Once you've understood those, embedding Perl in C is easy. -Since C has no built-in function for integer exponentiation, let's +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, since Perl implements ** with C's I function). First +sounds, because Perl implements ** with C's I function). First I'll create a stub exponentiation function in I: sub expo { @@ -503,7 +535,6 @@ I that contains all the perlguts necessary to push the two arguments into I and to pop the return value out. Take a deep breath... - #include #include #include @@ -539,6 +570,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 ***/ @@ -555,6 +587,278 @@ Compile and run: % power 3 to the 4th power is 81. +=head2 Maintaining a persistent interpreter + +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. + +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 C
. 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 C, compiled into a newly +constructed interpreter, and subsequently cleaned out with +C 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 L. 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 L, We'll +call the subroutine C which lives in the +file C 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 Ced 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 L 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; + } + + #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 = ; + 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; + + #take a look if you want + #print Devel::Symdump->rnew($package)->as_string, $/; + } + + 1; + + __END__ + + /* persistent.c */ + #include + #include + + /* 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)); + } + } + + 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 + +=head2 Maintaining multiple interpreter instances + +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 I +the next interpreter is constructed. By default, the global variable +C is set to C<0>, since extra cleaning isn't +needed when a program has only one interpreter. + +Setting C to C<1> makes everything squeaky clean: + + perl_destruct_level = 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 I 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 +C<-DMULTIPLICITY> flag when building Perl. By default, that sets +C to C<1>. + +Let's give it a try: + + + #include + #include + + /* 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 @@ -612,7 +916,7 @@ counterpart for each of the extension's XSUBs. Don't worry about this part; leave that to the I and extension authors. If your extension is dynamically loaded, DynaLoader creates I for you on the fly. In fact, if you have a working DynaLoader then there -is rarely any need to statically link in any other extensions. +is rarely any need to link in any other extensions statically. Once you have this code, slap it into the second argument of I: @@ -623,7 +927,7 @@ Once you have this code, slap it into the second argument of I: Then compile: - % cc -o interp interp.c `perl -MExtUtils::Embed -e ldopts` + % cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts` % interp use Socket; @@ -633,7 +937,7 @@ Then compile: B can also automate writing the I glue code. - % perl -MExtUtils::Embed -e xsinit -o perlxsi.c + % 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` @@ -644,20 +948,34 @@ Consult L and L for more details. =head1 MORAL You can sometimes I in C, but -you can always I in Perl. Since you can use +you can always I in Perl. Because you can use each from the other, combine them as you wish. =head1 AUTHOR -Jon Orwant Forwant@media.mit.eduE>, -co-authored by Doug MacEachern Fdougm@osf.orgE>, -with contributions from -Tim Bunce, Tom Christiansen, Dov Grobgeld, and Ilya -Zakharevich. +Jon Orwant and > and Doug MacEachern >, +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. -June 17, 1996 +April 14, 1997 -Some of this material is excerpted from my book: I, -Waite Group Press, 1996 (ISBN 1-57169-064-6) and appears +Some of this material is excerpted from Jon Orwant's book: I, Waite Group Press, 1996 (ISBN 1-57169-064-6) and appears courtesy of Waite Group Press. + +=head1 COPYRIGHT + +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.