perlembed.pod

来自「ARM上的如果你对底层感兴趣」· POD 代码 · 共 1,030 行 · 第 1/3 页

POD
1,030
字号
            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;

     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(ERRSV))
                fprintf(stderr, "eval error: %s\n", SvPV(ERRSV,PL_na));
        }
     }

     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 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<before>
the next interpreter is constructed.  By default, the global variable
C<PL_perl_destruct_level> is set to C<0>, since extra cleaning isn't
needed when a program has only one interpreter.

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 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<PL_perl_destruct_level> to C<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);
 }


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
that 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 extensions
on its own.  A little glue will help.  Up until now you've been
calling 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 between
Perl and linked C/C++ routines.  Let's take a look some pieces of I<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);
 }

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
I<Module::bootstrap()> and is invoked when you say I<use Module>.  In
turn, this hooks into an XSUB, I<boot_Module>, which creates a Perl
counterpart for each of the extension's XSUBs.  Don't worry about this
part; leave that to the I<xsubpp> and extension authors.  If your
extension is dynamically loaded, DynaLoader creates I<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 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> and L<perlguts> for more details.

=head1 Embedding Perl under Win32

At the time of this writing (5.004), there are two versions of Perl
which run under Win32.  (The two versions are merging in 5.005.)
Interfacing to ActiveState'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 ActiveState's
Perl runtime.  For details, see the Perl for Win32 FAQ at
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
B<genmake>, which generates a simple makefile to build a program from
a 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 Microsoft
Developer Studio.  In this case, run this to generate perlxsi.c:

 perl -MExtUtils::Embed -e xsinit

Create a new project and Insert -> Files into Project: perlxsi.c,
perl.lib, and your own source files, e.g. interp.c.  Typically you'll
find perl.lib in B<C:\perl\lib\CORE>, if not, you should see the
B<CORE> directory relative to C<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.
Finally, select Build -> Build interp.exe and you're ready to go.

=head1 MORAL

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


=head1 AUTHOR

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

Doug MacEachern has an article on embedding in Volume 1, Issue 4 of
The Perl Journal (http://tpj.com).  Doug is also the developer of the
most 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_perl
have used this model for Oracle, Netscape and Internet Information
Server Perl plugins.

July 22, 1998

=head1 COPYRIGHT

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

Permission is granted to make and distribute verbatim copies of this
documentation provided the copyright notice and this permission notice are
preserved on all copies.

Permission is granted to copy and distribute modified versions of this
documentation under the conditions for verbatim copying, provided also
that they are marked clearly as modified versions, that the authors'
names and title are unchanged (though subtitles and additional
authors' names may be added), and that the entire resulting derived
work is distributed under the terms of a permission notice identical
to this one.

Permission is granted to copy and distribute translations of this
documentation into another language, under the above conditions for
modified versions.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?