📄 perlembed.pod
字号:
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 <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; STRLEN n_a; 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; call_argv("Embed::Persistent::eval_file", G_DISCARD | G_EVAL, args); /* check $@ */ if(SvTRUE(ERRSV)) fprintf(stderr, "eval error: %s\n", SvPV(ERRSV,n_a)); } } PL_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 instancesSome rare applications will need to create more than one interpreterduring a session. Such an application might sporadically decide torelease any resources associated with the interpreter.The program must take care to ensure that this takes place I<before>the next interpreter is constructed. By default, when perl is notbuilt with any special options, the global variableC<PL_perl_destruct_level> is set to C<0>, since extra cleaning isn'tusually needed when a program only ever creates a single interpreterin its entire lifetime.Setting C<PL_perl_destruct_level> to C<1> makes everything squeaky clean: PL_perl_destruct_level = 1; while(1) { ... /* reset global variables here with PL_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<perl_destruct()> is called, the interpreter's syntax parse treeand symbol tables are cleaned up, and global variables are reset.Now suppose we have more than one interpreter instance running at thesame time. This is feasible, but only if you used the Configure optionC<-Dusemultiplicity> or the options C<-Dusethreads -Duseithreads> whenbuilding Perl. By default, enabling one of these Configure optionssets the per-interpreter global variable C<PL_perl_destruct_level> toC<1>, so that thorough cleaning is automatic.Using C<-Dusethreads -Duseithreads> rather than C<-Dusemultiplicity>is more appropriate if you intend to run multiple interpretersconcurrently in different threads, because it enables support forlinking in the thread libraries of your system with the 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_SET_CONTEXT(one_perl); perl_construct(one_perl); PERL_SET_CONTEXT(two_perl); perl_construct(two_perl); PERL_SET_CONTEXT(one_perl); perl_parse(one_perl, NULL, 3, one_args, (char **)NULL); PERL_SET_CONTEXT(two_perl); perl_parse(two_perl, NULL, 3, two_args, (char **)NULL); PERL_SET_CONTEXT(one_perl); perl_run(one_perl); PERL_SET_CONTEXT(two_perl); perl_run(two_perl); PERL_SET_CONTEXT(one_perl); perl_destruct(one_perl); PERL_SET_CONTEXT(two_perl); perl_destruct(two_perl); PERL_SET_CONTEXT(one_perl); perl_free(one_perl); PERL_SET_CONTEXT(two_perl); perl_free(two_perl); }Note the calls to PERL_SET_CONTEXT(). These are necessary to initializethe global state that tracks which interpreter is the "current" one onthe particular process or thread that may be running it. It shouldalways be used if you have more than one interpreter and are makingperl API calls on both interpreters in an interleaved fashion.PERL_SET_CONTEXT(interp) should also be called whenever C<interp> isused by a thread that did not create it (using either perl_alloc(), orthe more esoteric perl_clone()).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 programIf you've played with the examples above and tried to embed a scriptthat I<use()>s a Perl module (such as I<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 extensionson its own. A little glue will help. Up until now you've beencalling I<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 betweenPerl and linked C/C++ routines. Let's take a look some pieces of I<perlmain.c>to see how Perl does this: static void xs_init (pTHX); EXTERN_C void boot_DynaLoader (pTHX_ CV* cv); EXTERN_C void boot_Socket (pTHX_ CV* cv); EXTERN_C void xs_init(pTHX) { char *file = __FILE__; /* DynaLoader is a special case */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); newXS("Socket::bootstrap", boot_Socket, file); }Simply put: for each extension linked with your Perl executable(determined during its initial configuration on yourcomputer or when adding a new extension),a Perl subroutine is created to incorporate the extension'sroutines. Normally, that subroutine is namedI<Module::bootstrap()> and is invoked when you say I<use Module>. Inturn, this hooks into an XSUB, I<boot_Module>, which creates a Perlcounterpart for each of the extension's XSUBs. Don't worry about thispart; leave that to the I<xsubpp> and extension authors. If yourextension is dynamically loaded, DynaLoader creates I<Module::bootstrap()>for you on the fly. In fact, if you have a working DynaLoader then thereis rarely any need to link in any other extensions statically.Once you have this code, slap it into the second argument of I<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"'B<ExtUtils::Embed> can also automate writing the I<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 L<perlxs>, L<perlguts>, and L<perlapi> for more details.=head1 Embedding Perl under Win32In general, all of the source code shown here should work unmodified underWindows.However, there are some caveats about the command-line examples shown.For starters, backticks won't work under the Win32 native command shell.The ExtUtils::Embed kit on CPAN ships with a script calledB<genmake>, which generates a simple makefile to build a program froma single C source file. It can be used like this: 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 MicrosoftDeveloper Studio. In this case, run this to generate perlxsi.c: perl -MExtUtils::Embed -e xsinitCreate a new project and Insert -> Files into Project: perlxsi.c,perl.lib, and your own source files, e.g. interp.c. Typically you'llfind perl.lib in B<C:\perl\lib\CORE>, if not, you should see theB<CORE> directory relative to C<perl -V:archlib>. The studio willalso need this path so it knows where to find Perl include files.This path can be added via the Tools -> Options -> Directories menu.Finally, select Build -> Build interp.exe and you're ready to go.=head1 MORALYou can sometimes I<write faster code> in C, butyou can always I<write code faster> in Perl. Because you can useeach from the other, combine them as you wish.=head1 AUTHORJon Orwant <F<orwant@tpj.com>> and Doug MacEachern<F<dougm@osf.org>>, with small contributions from Tim Bunce, TomChristiansen, Guy Decoux, Hallvard Furuseth, Dov Grobgeld, and IlyaZakharevich.Doug MacEachern has an article on embedding in Volume 1, Issue 4 ofThe Perl Journal (http://tpj.com). Doug is also the developer of themost widely-used Perl embedding: the mod_perl system(perl.apache.org), which embeds Perl in the Apache web server.Oracle, Binary Evolution, ActiveState, and Ben Sugars's nsapi_perlhave used this model for Oracle, Netscape and Internet InformationServer Perl plugins.July 22, 1998=head1 COPYRIGHTCopyright (C) 1995, 1996, 1997, 1998 Doug MacEachern and Jon Orwant. AllRights Reserved.Permission is granted to make and distribute verbatim copies of thisdocumentation provided the copyright notice and this permission notice arepreserved on all copies.Permission is granted to copy and distribute modified versions of thisdocumentation under the conditions for verbatim copying, provided alsothat they are marked clearly as modified versions, that the authors'names and title are unchanged (though subtitles and additionalauthors' names may be added), and that the entire resulting derivedwork is distributed under the terms of a permission notice identicalto this one.Permission is granted to copy and distribute translations of thisdocumentation into another language, under the above conditions formodified versions.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -