home *** CD-ROM | disk | FTP | other *** search
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <HTML>
-
- <HEAD>
- <TITLE>ActivePerl faq10 - Embedding and Extending</TITLE>
- <LINK rev="made" href="mailto:support@ActiveState.com">
- <META name="GENERATOR" charset="iso-8859-1" content="Microsoft FrontPage 4.0">
- <META name="ProgId" content="FrontPage.Editor.Document">
- <LINK rel="STYLESHEET" href="../../Active.css" type="text/css" media="screen">
- </HEAD>
-
- <BODY bgcolor="#ffffff">
-
- <!-- beginning of leaf header-->
- <TABLE border="0" cellpadding="0" cellspacing="0" width="100%">
- <TR>
- <TD class="block" valign="MIDDLE" width="100%" bgcolor="#cccccc"><FONT size="+1"><STRONG>
- <P class="block"> ActivePerl FAQ</P>
- </STRONG></FONT></TD>
- </TR>
- </TABLE>
- <BR>
- <!-- end of leaf content--> <!-- INDEX BEGIN -->
- <UL>
- <LI><A href="#NAME">NAME</A></LI>
- <LI><A href="#DESCRIPTION">DESCRIPTION</A>
- <UL>
- <LI><A href="#How_do_I_write_an_extension_for_">How do I write an extension for ActivePerl?</A></LI>
- <LI><A href="#How_do_I_embed_the_Perl_interpre">How do I embed the Perl interpreter into my
- C/C++ program?</A></LI>
- <LI><A href="#I_have_a_program_with_perl_embed">I have a program with perl embedded from the
- standard distribution.</A></LI>
- </UL>
- </LI>
- <LI><A href="#AUTHOR_AND_COPYRIGHT">AUTHOR AND COPYRIGHT</A></LI>
- </UL>
- <!-- INDEX END -->
- <HR>
- <H1><A name="NAME">NAME</A></H1>
- <P>perlwin32faq10 - Embedding and Extending</P>
- <HR>
- <H1><A name="DESCRIPTION">DESCRIPTION</A></H1>
- <P>Techniques for Embedding and Extending ActivePerl</P>
- <HR>
- <H2><A name="How_do_I_write_an_extension_for_">How do I write an extension for ActivePerl?</A></H2>
- <P>Writing extensions in <FONT size="-1">C</FONT> or <FONT size="-1">C++</FONT> for ActivePerl is
- identical to writing them for standard Perl. Consult the perlxstut document for complete information
- and pointers to other sources of information.</P>
- <P>As a result of the oneperl effort, you now longer need to build ActivePerl from the source
- distribution to write or compile extensions. The Perl installation will detect your <FONT size="-1">C</FONT>
- compiler (currently, just Visual <FONT size="-1">C++),</FONT> and configure Perl to use it for
- compiling extensions.</P>
- <P>Note that writing extensions in <FONT size="-1">C</FONT> or <FONT size="-1">C++</FONT> is not
- easy. You need to have experience writing <FONT size="-1">C</FONT> programs for Windows platforms
- before you should even think about writing an extension.</P>
- <HR>
- <H2><A name="How_do_I_embed_the_Perl_interpre">How do I embed the Perl interpreter into my C/C++
- program?</A></H2>
- <P>As of build 500, this is quite easy. ActivePerl exposes Perl's internals through a <FONT size="-1">C++</FONT>
- object called <FONT size="-1">PERL_OBJECT.</FONT> Among other things, <FONT size="-1">PERL_OBJECT</FONT>
- simplifies the creation of multiple Perl interpreters within a single process.</P>
- <P>To embed ActivePerl in your own application, you must have the following:</P>
- <UL>
- <LI>
- <P>Microsoft Visual <FONT size="-1">C++</FONT></P>
- </LI>
- <LI>
- <P><FONT size="-1">A</FONT> binary release of ActivePerl (build 500 or later)</P>
- </LI>
- <LI>
- <P>The ActivePerl source code (the version of the source code must match the build of your
- binary version of Perl)</P>
- </LI>
- </UL>
- <P>Before you can compile an application that embeds ActivePerl, you must compile Perl from source.
- This does not mean that you must install Perl from source - the reason that you must compile Perl
- from source is that the compilation process creates the <EM>DynaLoader.c</EM> source code file,
- which is required if you want to use any extensions in your application.</P>
- <P>To compile Perl from source:</P>
- <OL>
- <LI><STRONG><A name="item_"></A></STRONG>
- <P>Change directory to the <EM>win32</EM> directory of your Perl source distribution and edit <EM>Makefile</EM>
- as necessary.</P>
- </LI>
- <LI>
- <P>Type <CODE>nmake</CODE>. This will compile all of Perl.</P>
- </LI>
- <LI>
- <P>Type <CODE>nmake test</CODE>. This ensures that Perl built correctly and passes all its
- tests.</P>
- </LI>
- <LI>
- <P>Perl is now compiled, and the <EM>DynaLoader.c</EM> file is created. If you did not install a
- binary release of Perl, you can issue the command <CODE>make install</CODE>, which will install
- Perl for you. This step is not necessary if you installed a binary release of Perl.</P>
- </LI>
- </OL>
- <P>Once you have compiled Perl from source, you have a source tree that can be used to build an
- embedded version of Perl. Here is a simple program that includes an embedded Perl interpreter. It is
- actually quite a bit like <EM>perl.exe</EM>. You can use all the command-line switches that are
- supported by perl, and you can also include the name of a script to execute. If you supply no
- switches, it will read in a Perl program from standard input, and executes the program when
- end-of-file is encountered. Save this file as <EM>MyPerl.cpp</EM> on your computer (remember to
- outdent the source code):</P>
- <PRE>
- /*
-
- 1) include perlhost.h. This header defines all the
- OS Interfaces that are used by the PERL_OBJECT.
- 2) define the host data structure 'CPerlHost'
- 3) call the CPerlHost member function PerlCreate,
- which calls perl_alloc and perl_construct
- 4) call the CPerlHost member function PerlParse
- 5) call the CPerlHost member function PerlRun
- 6) when done, call the CPerlHost member function PerlDestroy,
- which calls perl_destruct and perl_free
-
- Including XSUB.h brings in the files that have macros to redefine
- the perl_* functions, to work with PERL_OBJECT. Note that these
- macros may cause problems when there are name collisions. A common
- problem is having a local variable that has the same name as a Perl
- function. To track down these name collisions compile using '/P'
- option with VC++ so that you can see what the preprocessor has done.
-
- */
- #include <EXTERN.h>
- #include <perl.h>
- #define NO_XSLOCKS
-
- // Bring in the macros that redefine perl_* functions to work with
- // PERL_OBJECT.
- //
- #include <XSUB.h>
-
- /* for Win32 */
- #include "win32iop.h"
- #include <fcntl.h>
- #include <perlhost.h>
- #include <stdio.h>
-
- // DynaLoader stuff.
- //
- char *staticlinkmodules[] = {
- "DynaLoader",
- NULL,
- };
-
- // More DynaLoader stuff.
- //
- EXTERN_C void boot_DynaLoader _((CV* cv _CPERLarg));
-
- static void
- xs_init(CPERLarg)
- {
- char *file = __FILE__;
- dXSUB_SYS;
- newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
- }
-
- CPerlObj *pPerl; // The Perl object used by the host.
-
- int main (int argc, char **argv, char **env)
- {
- CPerlHost host; // The Perl host
- host.PerlCreate(); // Create an instance of the Perl Interpreter
-
- printf("Welcome to my very own Perl!\n\n");
-
- // Read arguments from the command line. If no script is named on the
- // command-line, and nothing is specified for -e, the interpreter will
- // read commands from standard input (just like Perl!).
- //
- host.PerlParse(xs_init, argc, argv, NULL);
-
- host.PerlRun(); // Run the interpreter.
- host.PerlDestroy(); // Destroy the interpreter.
- return 0;
- }
- </PRE>
- <P>To compile this program, you must use the following <EM>Makefile</EM>. Be sure to update <CODE>LIBDIR</CODE>
- to point to the <EM>CORE</EM> subdirectory of your Perl binary installation, and update <CODE>SRCDIR</CODE>
- to point to the <EM>src</EM> directory of the Perl source code that you compiled earlier. Save this
- file as <EM>Makefile</EM> (remember to outdent the contents):</P>
- <PRE>
- LIBDIR = C:\Perl\5.00500\lib\MSWin32-x86\CORE
- SRCDIR = C:\5.00500\src
-
- LIBS = oldnames.lib kernel32.lib user32.lib winspool.lib advapi32.lib \
- shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib \
- wsock32.lib version.lib PerlCRT.lib $(LIBDIR)\PerlCore.lib
- </PRE>
- <PRE>
- CCFLAGS = -c -I$(LIBDIR) -Gf -W3 -DWIN32 -D_CONSOLE -DPERL_CORE \
- -O2 -MD -DNDEBUG -TP -GX -DPERL_OBJECT -UPERLDLL
- CCDYNA = $(CCFLAGS) -I$(SRCDIR)\ext\DynaLoader
-
- all:
- cl.exe $(CCFLAGS) -Fo.\MyPerl.obj MyPerl.cpp
- cl.exe $(CCFLAGS) -Fo.\win32.obj $(SRCDIR)\win32\win32.c
- cl.exe $(CCFLAGS) -Fo.\win32sck.obj $(SRCDIR)\win32\win32sck.c
- cl.exe $(CCFLAGS) -Fo.\DynaLoader.obj \
- $(SRCDIR)\ext\DynaLoader\DynaLoader.c
- link.exe -nologo -nodefaultlib -release -machine:x86 $(LIBS) \
- -subsystem:console MyPerl.obj win32.obj win32sck.obj \
- DynaLoader.obj setargv.obj
- </PRE>
- <P>Make sure that <EM>PerlCRT.lib</EM> has been installed properly. For more information, see <A href="#How_do_I_write_an_extension_for_">How
- do I write an extension for ActivePerl?</A>.</P>
- <P>You can then compile <EM>MyPerl.cpp</EM> by typing <CODE>nmake</CODE> at the command line (make
- sure that both <EM>MyPerl.cpp</EM> and <EM>Makefile</EM> are in your current working directory).
- This will produce the file <EM>MyPerl.exe</EM>, which you can run at the command line as though it
- were <EM>perl.exe</EM>:</P>
- <PRE>
- C:\MyPerl>myperl -e "print qq[Hello, World\n];"
- Welcome to my very own Perl!
-
- Hello, World
- </PRE>
- <P>or:</P>
- <PRE>
- C:\MyPerl>myperl
- Welcome to my very own Perl!
-
- print "Hello, world\n";
- ^Z
- Hello, world
- </PRE>
- <P>If you want to use modules and extensions from your local Perl installation, you'll need to do
- one of two things. The simplest thing you can do is copy your executable to the same location as
- perl.exe.</P>
- <P>If this is not an option, you need to tell your program where to find things. This can be
- accomplished by setting the <CODE>PERL5LIB</CODE> environment variable with something like:</P>
- <PRE>
- set PERL5LIB=C:\Perl\5.00500\lib;C:\Perl\site\5.00500\lib;C:\Perl\site\lib
- </PRE>
- <P>Then you can use modules and extensions from your local Perl installation:</P>
- <PRE>
- C:\MyPerl>MyPerl -MWin32::OLE -e "print $Win32::OLE::VERSION;"
- Welcome to my very own Perl!
-
- 0.0807
- </PRE>
- <P>The following example is based on the PerlPower example from Doug MacEachern and Jon Orwant's
- perlembed document (this is part of Perl, and you should have a copy included with ActivePerl). You
- should save the following program as <EM>PerlPower.cpp</EM>:</P>
- <PRE>
- /*
- To show how to embed Perl with PERL_OBJECT defined, we will show the
- changes needed for the PerlPower sample that is in perlembed.pod.
-
- 1) include perlhost.h. This header defines all the
- OS Interfaces that are used by the PERL_OBJECT.
- 2) define the host data structure 'CPerlHost'
- 3) call the CPerlHost member function PerlCreate,
- which calls perl_alloc and perl_construct
- 4) call the CPerlHost member function PerlParse
- 5) call the CPerlHost member function PerlRun
- 6) call any of the perl_call_* functions
- 7) when done, call the CPerlHost member function PerlDestroy,
- which calls perl_destruct and perl_free
-
- Including XSUB.h brings in the files that have macros to redefine the
- perl_* functions, to work with PERL_OBJECT. Note that these macros may
- cause problems when there are name collisions. A common problem is
- having a local variable that has the same name as a Perl function. To
- track down these name collisions compile using '/P' option with VC++ so
- that you can see what the preprocessor has done.
-
- */
-
- #include <EXTERN.h>
- #include <perl.h>
-
- #define NO_XSLOCKS
-
- // Bring in the macros that redefine perl_* functions to work with
- // PERL_OBJECT.
- //
- #include <XSUB.h>
-
- /* for Win32 */
- #include "win32iop.h"
- #include <fcntl.h>
- #include <perlhost.h>
-
- // DynaLoader stuff.
- //
- char *staticlinkmodules[] = {
- "DynaLoader",
- NULL,
- };
-
- // More DynaLoader stuff.
- //
- EXTERN_C void boot_DynaLoader _((CV* cv _CPERLarg));
- static void
- xs_init(CPERLarg)
- {
- char *file = __FILE__;
- dXSUB_SYS;
- newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
- }
-
- CPerlObj *pPerl;
-
- 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)
- {
- CPerlHost host;
-
- host.PerlCreate();
-
- // Don't use argv or argc for embedding. Instead, we'll pretend that
- // we gave it the arguments "-e 0".
- //
- char *embedding[] = { "", "-e", "0" };
- host.PerlParse(xs_init, 3, embedding, NULL);
-
- // Define the expo() function.
- //
- perl_eval_pv("sub expo { my($a, $b) = @_; return $a ** $b; }", TRUE);
-
- host.PerlRun();
-
- PerlPower(3, 4); /*** Compute 3 ** 4 ***/
-
- host.PerlDestroy();
- return 0;
- }
- </PRE>
- <P>The following <EM>Makefile</EM> can be used to compile <EM>PerlPower.cpp</EM>:</P>
- <PRE>
- LIBDIR = C:\Perl\5.00468\lib\MSWin32-x86\CORE
- SRCDIR = C:\betab9\src
-
- LIBS = oldnames.lib kernel32.lib user32.lib winspool.lib advapi32.lib \
- shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib \
- wsock32.lib version.lib PerlCRT.lib $(LIBDIR)\PerlCore.lib
-
- CCFLAGS = -c -I$(LIBDIR) -Gf -W3 -DWIN32 -D_CONSOLE -DPERL_CORE \
- -O2 -MD -DNDEBUG -TP -GX -DPERL_OBJECT -UPERLDLL
- CCDYNA = $(CCFLAGS) -I$(SRCDIR)\ext\DynaLoader
-
- all:
- cl.exe $(CCFLAGS) -Fo.\PerlPower.obj PerlPower.cpp
- cl.exe $(CCFLAGS) -Fo.\win32.obj $(SRCDIR)\win32\win32.c
- cl.exe $(CCFLAGS) -Fo.\win32sck.obj $(SRCDIR)\win32\win32sck.c
- cl.exe $(CCFLAGS) -Fo.\DynaLoader.obj \
- $(SRCDIR)\ext\DynaLoader\DynaLoader.c
- link.exe -nologo -nodefaultlib -release -machine:x86 $(LIBS) \
- -subsystem:console PerlPower.obj win32.obj win32sck.obj \
- DynaLoader.obj setargv.obj
- </PRE>
- <P>As with the <EM>MyPerl.cpp</EM> example <EM>Makefile</EM>, be sure that <CODE>SRCDIR</CODE> and <CODE>LIBDIR</CODE>
- point to the correct directories. You can compile <EM>PerlPower.cpp</EM> by typing <CODE>nmake</CODE>
- at the command line (make sure that both <EM>PerlPower.cpp</EM> and <EM>Makefile</EM> are in your
- current working directory). This will produce the file <EM>PerlPower.exe</EM>, which you can run at
- the command line:</P>
- <PRE>
- C:\PerlPower>PerlPower
- 3 to the 4th power is 81.
- </PRE>
- <P>You should definitely read the perlembed document in its entirety to get an overview of the
- issues involved with embedding Perl. Then, you can use the <EM>MyPerl.cpp</EM> and <EM>PerlPower.cpp</EM>
- as guides for embedding ActivePerl.</P>
- <HR>
- <H2><A name="I_have_a_program_with_perl_embed">I have a program with perl embedded from the standard
- distribution. Why won't it compile with ActivePerl?</A></H2>
- <P>ActivePerl exposes the Perl interpreter in a slightly different fashion than standard Perl. For
- information on how to embed using ActivePerl, see <A href="#How_do_I_embed_the_Perl_interpre">How do
- I embed the Perl interpreter into my C/C++ program?</A>.</P>
- <HR>
- <H1><A name="AUTHOR_AND_COPYRIGHT">AUTHOR AND COPYRIGHT</A></H1>
- <P> </P>
- <P>This <FONT size="-1">FAQ</FONT> was originally assembled and maintained by Evangelo Prodromou. It
- has been revised and updated by Brian Jepson of O'Reilly & Associates, David Grove, David
- Dmytryshyn, and David Sparks of ActiveState.</P>
- <P>This <FONT size="-1">FAQ</FONT> is in the public domain. If you use it, however, please ensure
- that you give credit to the original authors. <!-- beginning of leaf footer-->
- </P>
- <TABLE border="0" cellpadding="0" cellspacing="0" width="100%">
- <TR>
- <TD class="block" valign="MIDDLE" width="100%" bgcolor="#cccccc"><FONT size="+1"><STRONG>
- <P class="block"> ActivePerl FAQ</P>
- </STRONG></FONT></TD>
- </TR>
- </TABLE>
- <!-- end of leaf footer-->
-
- </BODY>
-
- </HTML>
-