=over 5
-=item Compiling your C program
+=item *
-=item Adding a Perl interpreter to your C program
+Compiling your C program
-=item Calling a Perl subroutine from your C program
+=item *
-=item Evaluating a Perl statement from your C program
+Adding a Perl interpreter to your C program
-=item Performing Perl pattern matches and substitutions from your C program
+=item *
-=item Fiddling with the Perl stack from your C program
+Calling a Perl subroutine from your C program
-=item Maintaining a persistent interpreter
+=item *
-=item Maintaining multiple interpreter instances
+Evaluating a Perl statement from your C program
-=item Using Perl modules, which themselves use C libraries, from your C program
+=item *
-=item Embedding Perl under Win32
+Performing Perl pattern matches and substitutions from your C program
+
+=item *
+
+Fiddling with the Perl stack from your C program
+
+=item *
+
+Maintaining a persistent interpreter
+
+=item *
+
+Maintaining multiple interpreter instances
+
+=item *
+
+Using Perl modules, which themselves use C libraries, from your C program
+
+=item *
+
+Embedding Perl under Win32
=back
{
my_perl = perl_alloc();
perl_construct(my_perl);
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_parse(my_perl, NULL, argc, argv, (char **)NULL);
perl_run(my_perl);
perl_destruct(my_perl);
perl_construct(my_perl);
perl_parse(my_perl, NULL, argc, argv, NULL);
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
/*** skipping perl_run() ***/
(the beginning of the Unix epoch), and the moment I began writing this
sentence.
-In this particular case we don't have to call I<perl_run>, but 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.
+In this particular case we don't have to call I<perl_run>, as we set
+the PL_exit_flag PERL_EXIT_DESTRUCT_END which executes END blocks in
+perl_destruct.
If you want to pass arguments to the Perl subroutine, you can add
strings to the C<NULL>-terminated C<args> list passed to
perl_construct( my_perl );
perl_parse(my_perl, NULL, 3, embedding, NULL);
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
/** Treat $a as an integer **/
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, embedding, NULL);
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
sv_setpv(text, "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 correct amount. The boy gives him back two of his own pennies and then the big shiny quarter that is his prize. -RICHH");
perl_construct( my_perl );
perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL);
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
PerlPower(3, 4); /*** Compute 3 ** 4 ***/
perl_construct(perl);
exitstatus = perl_parse(perl, NULL, 2, embedding, NULL);
-
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
if(!exitstatus) {
exitstatus = perl_run(perl);
foo says: hello
Enter file name: ^C
+=head2 Execution of END blocks
+
+Traditionally END blocks have been executed at the end of the perl_run.
+This causes problems for applications that never call perl_run. Since
+perl 5.7.2 you can specify C<PL_exit_flags |= PERL_EXIT_DESTRUCT_END>
+to get the new behaviour. This also enables the running of END blocks if
+the perl_prase fails and C<perl_destruct> will return the exit value.
+
=head2 Maintaining multiple interpreter instances
Some rare applications will need to create more than one interpreter
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
+the next interpreter is constructed. By default, when perl is not
+built with any special options, 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.
+usually needed when a program only ever creates a single interpreter
+in its entire lifetime.
Setting C<PL_perl_destruct_level> to C<1> makes everything squeaky clean:
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>.
+same time. This is feasible, but only if you used the Configure option
+C<-Dusemultiplicity> or the options C<-Dusethreads -Duseithreads> when
+building Perl. By default, enabling one of these Configure options
+sets the per-interpreter global variable C<PL_perl_destruct_level> to
+C<1>, so that thorough cleaning is automatic.
+
+Using C<-Dusethreads -Duseithreads> rather than C<-Dusemultiplicity>
+is more appropriate if you intend to run multiple interpreters
+concurrently in different threads, because it enables support for
+linking in the thread libraries of your system with the interpreter.
Let's give it a try:
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 initialize
+the global state that tracks which interpreter is the "current" one on
+the particular process or thread that may be running it. It should
+always be used if you have more than one interpreter and are making
+perl API calls on both interpreters in an interleaved fashion.
+
+PERL_SET_CONTEXT(interp) should also be called whenever C<interp> is
+used by a thread that did not create it (using either perl_alloc(), or
+the more esoteric perl_clone()).
Compile as usual: