diff options
Diffstat (limited to 'reference/C/MAN/perlembed.htm')
-rw-r--r-- | reference/C/MAN/perlembed.htm | 885 |
1 files changed, 885 insertions, 0 deletions
diff --git a/reference/C/MAN/perlembed.htm b/reference/C/MAN/perlembed.htm new file mode 100644 index 0000000..2609362 --- /dev/null +++ b/reference/C/MAN/perlembed.htm @@ -0,0 +1,885 @@ +<TITLE>perlembed</TITLE> +<body background=/C_ref/GRAPHICS/bg1.gif> +<hr> +<pre> + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + +<h3>NAME +</h3> perlembed - how to embed perl in your C program + +<h3>DESCRIPTION +</h3> 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 backquotes and the system entry in the + perlfunc manpage and the exec entry 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 use + entry in the perlmod manpage and the require entry in + the perlmod manpage. + + Use C from C? + Rethink your design. + + Use Perl from C? + Read on... + + ROADMAP + + the section on Compiling your C program + + There's one example in each of the five 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 + + This documentation is UNIX specific. + + Compiling your C program + + Every C program that uses Perl must link in the perl + library. + + + +<h3>30/Jan/96 perl 5.003 with 1 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + 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.) + + Your C program will--usually--allocate, "run", and + deallocate a PerlInterpreter object, which is defined in + the perl library. + + 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, which you'll also need) will reside + in a directory resembling 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 -e 'use Config; print $Config{archlib}' + + Here's how you might compile the example in the next + section, the section on Adding a Perl interpreter to your + C program, 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 (cc, gcc, + et al.) and 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 or 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 -e 'use Config; print $Config{libs}' + + + + +<h3>30/Jan/96 perl 5.003 with 2 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + Adding a Perl interpreter to youur C program + + 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, non-portable version + of 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 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, env); + perl_run(my_perl); + perl_destruct(my_perl); + perl_free(my_perl); + } + + Now compile this program (I'll call it interp.c) into an + executable: + + % 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 + + 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 yyour C program + + To call individual Perl subroutines, you'll need to remove + the call to perl_run() and replace it with a call to + perl_call_argv(). + + + +<h3>30/Jan/96 perl 5.003 with 3 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + That's shown below, in a program I'll call showtime.c. + + #include <stdio.h> + #include <EXTERN.h> + #include <perl.h> + + static PerlInterpreter *my_perl; + + int main(int argc, char **argv, char **env) + { + my_perl = perl_alloc(); + perl_construct(my_perl); + + perl_parse(my_perl, NULL, argc, argv, env); + + /*** This replaces perl_run() ***/ + perl_call_argv("showtime", G_DISCARD | G_NOARGS, argv); + 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 -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, demonstrated in the last + section of this document: the section on Fiddling with the + Perl stack from your C program + + + + + +<h3>30/Jan/96 perl 5.003 with 4 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + Evaluating a Perl statement fr<h3>om your C program +</h3> + 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 the perl_eval_sv entry in the perlguts + manpage). Look for updates to this document soon. + + One way to evaluate a Perl string is to define a function + (we'll call ours perl_eval()) that wraps around Perl's the + eval entry in the perlfunc manpage. + + 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 the require entry in the + perlmod manpage or the do entry in the perlfunc manpage to + include external Perl files. + + Our perl_eval() 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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>30/Jan/96 perl 5.003 with 5 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + #include <stdio.h> + #include <EXTERN.h> + #include <perl.h> + + 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, env); + + /** 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); + } + + All of those strange functions with sv in their names help + convert Perl scalars to C types. They're described in the + perlguts manpage. + + 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 + + + + + + +<h3>30/Jan/96 perl 5.003 with 6 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + Performing Perl pattern matche<h3>s and substitutions from +</h3> your C program + + Our perl_eval() lets us evaluate strings of Perl code, so + we can define some functions that use it to "specialize" + in matches and substitutions: match(), substitute(), and + matches(). + + 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 + "/\\b\\w*\\b/"), 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. + + int matches(char *string, char *pattern, char **matches[]); + + Given a string, a pattern, and a pointer to an empty array + of strings, evaluates $string =~ $pattern in an array + context, and fills in matches with the array elements + (allocating memory as it does so), returning the number of + matches found. + + Here's a sample program, match.c, that uses all three: + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>30/Jan/96 perl 5.003 with 7 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + #include <stdio.h> + #include <EXTERN.h> + #include <perl.h> + + static PerlInterpreter *my_perl; + + int 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. + ** + ** Returns 1 if the match was successful; 0 otherwise. + **/ + char match(char *string, char *pattern) + { + char *command; + command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 37); + sprintf(command, "$string = '%s'; $return = $string =~ %s", + string, pattern); + perl_eval(command); + free(command); + return SvIV(perl_get_sv("return", FALSE)); + } + + /** 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. + **/ + int substitute(char *string[], char *pattern) + { + char *command; + 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)); + } + + /** matches(string, pattern, matches) + ** + ** Used for matches in an array context. + + + +<h3>30/Jan/96 perl 5.003 with 8 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + ** + ** Returns the number of matches, + ** and fills in **matches with the matching substrings (allocates memory!) + **/ + int matches(char *string, char *pattern, char **matches[]) + { + char *command; + SV *current_match; + AV *array; + I32 num_matches; + STRLEN length; + int i; + + command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 38); + sprintf(command, "$string = '%s'; @array = ($string =~ %s)", + string, pattern); + perl_eval(command); + free(command); + array = perl_get_av("array", FALSE); + num_matches = av_len(array) + 1; /** assume $[ is 0 **/ + *matches = (char **) malloc(sizeof(char *) * num_matches); + for (i = 0; i <= num_matches; i++) { + current_match = av_shift(array); + (*matches)[i] = SvPV(current_match, length); + } + return num_matches; + } + + main (int argc, char **argv, char **env) + { + char *embedding[] = { "", "-e", "sub _eval_ { eval $_[0] }" }; + char *text, **matches; + int num_matches, i; + int j; + + my_perl = perl_alloc(); + perl_construct( my_perl ); + + perl_parse(my_perl, NULL, 3, embedding, env); + + 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 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 corre<h3>ct amount. The boy gives him back two of his own pennies and then the big shiny quarter that is his prize. -RICHH"); +</h3> + if (perl_match(text, "m/quarter/")) /** Does text contain 'quarter'? **/ + printf("perl_match: Text contains the word 'quarter'.\n\n"); + else + printf("perl_match: Text doesn't contain the word 'quarter'.\n\n"); + + if (perl_match(text, "m/eighth/")) /** Does text contain 'eighth'? **/ + printf("perl_match: Text contains the word 'eighth'.\n\n"); + else + printf("perl_match: Text doesn't contain the word 'eighth'.\n\n"); + + /** Match all occurrences of /wi../ **/ + + + +<h3>30/Jan/96 perl 5.003 with 9 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + num_matches = perl_matches(text, "m/(wi..)/g", &matches); + + printf("perl_matches: m/(wi..)/g found %d matches...\n", num_matches); + for (i = 0; i < num_matches; i++) + printf("match: %s\n", matches[i]); + printf("\n"); + for (i = 0; i < num_matches; i++) { + free(matches[i]); + } + free(matches); + + /** Remove all vowels from text **/ + num_matches = perl_substitute(&text, "s/[aeiou]//gi"); + if (num_matches) { + printf("perl_substitute: s/[aeiou]//gi...%d substitutions made.\n", + num_matches); + printf("Now text is: %s\n\n", text); + } + + /** Attempt a substitution + if (!perl_substitute(&text, "s/Perl/C/")) { + printf("perl_substitute: s/Perl/C...No substitution made.\n\n"); + } + + free(text); + + perl_destruct(my_perl); + perl_free(my_perl); + } + + which produces the output + + perl_match: Text contains the word 'quarter'. + + perl_match: Text doesn't contain the word 'eighth'. + + perl_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, 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 s<h3>qzy 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 +</h3> + perl_substitute: s/Perl/C...No substitution made. + + =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 + + + +<h3>30/Jan/96 perl 5.003 with 10 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + 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. + + Since 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() 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... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>30/Jan/96 perl 5.003 with 11 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + + #include <stdio.h> + #include <EXTERN.h> + #include <perl.h> + + 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, NULL, argc, my_argv, env); + + PerlPower(3, 4); /*** Compute 3 ** 4 ***/ + + perl_destruct(my_perl); + perl_free(my_perl); + } + + + 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 + 3 to the 4th power is 81. + + + + + + +<h3>30/Jan/96 perl 5.003 with 12 +</h3> + + + + +<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1) +</h3> + +<h3>MORAL +</h3> You can sometimes write faster code in C, but you can + always write code faster in Perl. Since you can use each + from the other, combine them as you wish. + +<h3>AUTHOR +</h3> Jon Orwant <orwant@media.mit.edu>, with contributions from + Tim Bunce, Tom Christiansen, Dov Grobgeld, and Ilya + Zakharevich. + + December 18, 1995 + + Some of this material is excerpted from my book: Perl 5 + Interactive, Waite Group Press, 1996 (ISBN 1-57169-064-6) + and appears courtesy of Waite Group Press. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3>30/Jan/96 perl 5.003 with 13 +</h3> + +</pre> +<P> +<hr> +<p> +<center> +<table border="2" width="80%"> +<tr align=center> +<td width="25%"> +<a href="../cref.html">Top</a> +</td><td width="25%"> +<a href="../master_index.html">Master Index</a> +</td><td width="25%"> +<a href="../SYNTAX/keywords.html">Keywords</a> +</td><td width="25%"> +<a href="../FUNCTIONS/funcref.htm">Functions</a> +</td> +</tr> +</table> +</center> +<p> +<hr> + +This manual page was brought to you by <i>mjl_man V-2.0</i> |