MatthewFrancis has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have a rather (to me) esoteric question, something perhaps tailor-made for the Perl Monks vaults of arcane knowledge. I'm attempting to embed the Perl Interpreter in some C code, and am having some problems... While I can get the code to compile (itself, no simple task) I get the following error when I run the executable:
Can't load module File::Glob, dynamic loading not available in this pe +rl. (You may need to build a new perl executable which either supports dynamic loading or has the File::Glob module statically linked into +it.) Compilation failed in require at search.pl line 6.
Hmmm, does this require DynaLoader? And - if so - how and where do I include it? I assume in my compile statement, but nothing I'm trying (e.g.)
cc codeGen.c -o codeGen -L/usr/local/lib /opt/perl/lib/5.6.1/PA-RISC1 +.1-thread-multi/auto/DynaLoader/DynaLoader.a -L/opt /perl/lib/5.6.1/PA-RISC1.1-thread-multi/CORE -lperl -lnsl -lnm -lmallo +c -ldld -lm -lpthread -lc -lndir -lcrypt -lsec -I/usr/local/ include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/opt/perl/lib/5.6 +.1/PA-RISC1.1-thread-multi/CORE
seems to be working. Unfortunately, I seem to be at a loss as to how to proceed. Thanks! MatthewFrancis

Replies are listed 'Best First'.
Re: Embedding Perl Interpreter/DynaLoader
by holo (Monk) on Dec 01, 2003 at 21:56 UTC

    I have a similar problem in linking a bunch of routines in a dynamic .so. DynaLoader works for me if I link to ELF (or a.out) when I use the ExtUtils::Embed parameters. This is a great module that tells you how your Perl was compiled:

    perl -MExtUtils::Embed -e ldopts -- DynaLoader

    Use the output of the above command while linking and (hopefully), you'll be fine. You might also fix the problem by linking File::Glob directly:

    perl -MExtUtils::Embed -e ldopts -- -std File::Glob

    I hope one of these works for you. Good Luck!

Re: Embedding Perl Interpreter/DynaLoader
by mpeppler (Vicar) on Dec 01, 2003 at 22:29 UTC
    Personally I use the ExtUtils::Embed option to generate the xs_init() code, and link that into my binary that includes perl functionality.

    Parts of my Makefile look like this:

    CONFIG_PM=-MConfig PRIVLIB=`$(PERL) $(CONFIG_PM) -e 'print $$Config{privlibexp}'` EXTUTILS_EMBED = $(PERL) -MExtUtils::Embed PERL_CFG_CCFLAGS = `$(PERL) $(CONFIG_PM) -e 'print "$$Config{ccflags} +$$Config{cccdlflags}"'` PERL_CFG_ARCHLIB = `$(PERL) $(CONFIG_PM) -e 'print $$Config{archlibexp +}'` PERL_CCFLAGS = -I$(PERL_CFG_ARCHLIB)/CORE $(PERL_CFG_CCFLAGS) $(PERL_H +OOKS) $(TRACE) STATIC_EXTS=Sybase::OpnSrv XS_INIT = `$(EXTUTILS_EMBED) -e xsinit -- -std $(PERL_STATIC_EXTS) $(S +TATIC_EXTS)` CC=`$(PERL) $(CONFIG_PM) -e 'print $$Config{cc}'` LD=`$(PERL) $(CONFIG_PM) -e 'print "$$Config{ld}\n"'` .... SRC=xp_perl.c perlxsi.c ... # other files OBJS=$(SRC:.c=.o) perlxsi.c: $(XS_INIT)
    This generates a perlxsi.c file like this:
    #include <EXTERN.h> #include <perl.h> EXTERN_C void xs_init (pTHXo); EXTERN_C void boot_Sybase__OpnSrv (pTHXo_ CV* cv); EXTERN_C void boot_DynaLoader (pTHXo_ CV* cv); EXTERN_C void xs_init(pTHXo) { char *file = __FILE__; dXSUB_SYS; newXS("Sybase::OpnSrv::bootstrap", boot_Sybase__OpnSrv, file); /* DynaLoader is a special case */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); }
    which bootstraps all of the static modules when the perl interpreter is started.

    Michael

Re: Embedding Perl Interpreter/DynaLoader
by MatthewFrancis (Acolyte) on Dec 01, 2003 at 23:07 UTC
    Thanks for your help - I've arrived at some new questions as a result!

    1) "perl -MExtUtils::Embed -e ccopts -e ldopts" does not work for me when I use it to pass parameters to my cc statement. The cc compiler complains of many unknown options. I took a look at the Config.pm file, and it references the gcc compiler. I don't believe we have that installed on our UNIX server - perhaps the admins loaded a precompiled binary of Perl, rendering ExtUtils useless for me in this fashion?

    2) I did use ExtUtils to produce an xsinit.c file, as follows:

    perl -MExtUtils::Embed -e xsinit -- -o xsinit.c -std
    But I can not compile this. When I try
    cc xsinit.c codeGen.c -o codeGen -L/lib/pa1.1 -L/usr/local/lib -I/usr/ +local/include -I/opt/perl/lib/5.6.1/PA-RISC1.1-t hread-multi/CORE -L/opt/perl/lib/5.6.1/PA-RISC1.1-thread-multi/auto/Dy +naLoader/DynaLoader.a -L/opt/perl/lib/5.6.1/PA-RISC1.1-threa d-multi/CORE -L/opt/perl/lib/5.6.1/PA-RISC1.1-thread-multi/CORE/libper +l.so -lmalloc -ldld -ldld -lperl -lm -lsec -lnsl -lnm -lpthr ead -lc -lndir -lcrypt -Dbool=char -DHAS_BOOL
    (gruesome, I know - I've tried to link/add every possible library) I get the following:
    xsinit.c: codeGen.c: /usr/ccs/bin/ld: Unsatisfied symbols: boot_DynaLoader (first referenced in xsinit.o) (code)
    My goal is to compile "codeGen.c", which contains an embedded Perl interpreter. What should I be loading in order to use boot_DynaLoader w/o compile problems? I can't think of any more directories to include.

    3) this problem only seems to arise when I attempt to use glob(). What is it about that function that would result in these errors?

    Thanks again good monks- I very much appreciate the help

    MatthewFrancis

      Here's your error:
      -L/opt/perl/lib/5.6.1/PA-RISC1.1-thread-multi/auto/DynaLoader/DynaLoad +er.a
      This tells the linker to add this directory to the directories to search for files to link.

      Remove the -L and you should be fine.

      Michael

      Embedding Perl into a program will usually only work if Perl and the other program are compiled with the same compiler. Try compiling your own Perl for embedding...

      About the dynaloader, I think there was an example how to include it somewhere in the embed PODs, it's just 2 or 3 lines of additional C code. But I cannot find it right now, sorry.


      Search, Ask, Know
Re: Embedding Perl Interpreter/DynaLoader
by MatthewFrancis (Acolyte) on Dec 02, 2003 at 00:05 UTC
    Thank you all again for the help, Per the suggestion, I removed the '-L' from the DynaLoader.a chunk, and things compiled fine. Whew!

    The compile string is now:

    cc '-Wl,-E' -I "/usr/local/include" -I "/opt/perl/lib/5.6.1/PA-RISC1.1 +-thread-multi/CORE" -o codeGen xsinit.c codeGen. c -L/usr/local/lib -L "/opt/perl/lib/5.6.1/PA-RISC1.1-thread-multi/COR +E" "/opt/perl/lib/5.6.1/PA-RISC1.1-thread-multi/auto/DynaLoa der/DynaLoader.a" -lperl -lnsl -lm -lc -lcrypt -lsec -L/usr/local/lib
    Unfortunately, when I run the executable I still get that same ol' frustrating error:
    Can't load module File::Glob, dynamic loading not available in this pe +rl. (You may need to build a new perl executable which either supports dynamic loading or has the File::Glob module statically linked into +it.) Compilation failed in require at search.pl line 8. BEGIN failed--compilation aborted at search.pl line 8. Undefined subroutine &main::search_files called at search.pl line 8.
    And, of course, things are lovely if I remove any reference to glob(). Beyond this point, I'm not sure how to create an executable that "supports dynamic loading". Hmmm, perhaps naively I thought DynaLoader.a would do that. Perhaps - if there are no more obvious things for me to try - I will make do w/o glob() as part of my embedded Perl.

    Thank you all,

    MatthewFrancis

      OK - now the problem is that the libperl.so/.a is from a build that does not include the dl_open.xs (or whichever implementation is used under HP-UX) module.

      Is the C compiler you are using the basic C compiler that comes with HP-UX?

      I have a feeling that if that's the case then that C compiler is an old K&R compiler that can't be used to build dynamically loadable modules, etc. Maybe it'd be worth it to download/install gcc? I think there is a site that offers binaries, similar to sunfreeware for Solaris.

      Michael

        Interesting. I've heard of these ".so" files before, but we don't have any on our server. All we've got is the libperl.a. Does this mean that our current Perl installation is broken/incomplete? If so, I am going to see what I can do about having our Perl reinstalled. For what it's worth, we're using (courtesy of of "perl -v"):
        Binary build 633 provided by ActiveState Corp. http://www.ActiveState. +com Built 21:04:57 Jun 17 2002
        If it's a binary build, then, perhaps the .so file was never there to begin with. Would you recommend actually building it ourselves, as opposed to working with a precompiled binary?

        Yes, I believe the compiler is the standard, no-frills HP-UX compiler.

        And - please forgive the remedial nature of my questions - how can I statically link the File::Glob module into my perl executable? What do I have to provide at the command line in order to make this happen?

        Thank you again, for the help

        MatthewFrancis