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

I have an app with an embedded perl interpretor which runs: "use XML::LibXML" on startup. That works fine, no errors.
I have a C function which attempts to use the function PmmNodeToSv which is in the LibXML.so library, but I get this error:
relocation error: ./plugins/perl/.libs/perl.so: undefined symbol: PmmN +odeToSv
How do I allow my C code to see this symbol? Should I link against the LibXML.so library? If so, is there a clean way to find where this library is programmatically?

2004-05-12 Edit by jdporter: Changed title from 'Relocation error with an embedded perl interpretor'

Replies are listed 'Best First'.
Re: Relocation error with an embedded perl interpreter
by Zaxo (Archbishop) on May 11, 2004 at 13:15 UTC

    The source of your C function should #include the correct libxml headers and be linked to libXML.

    After Compline,
    Zaxo

      My app is linked against -lxml2. The trouble is the PmmNodeToSv is provided by the perl library, not the c library. i.e. PmmNodeToSv is in: /usr/lib/perl5/vendor_perl/5.8.3/i686-linux/auto/XML/LibXML/LibXML.so I could link against that I guess, but how to find out where that library is on other peoples systems cleanly?
        Well, I would imagine that if Perl can do it, so can you. You have the source; I would start looking at Dynaloader since that seems to be the guts behind everything.

        I admit that I'm not sure how well that would work; you might need to do some dynamic linking tricks to get the address of your function *after* the .so is loaded by Perl.

        --Stevie-O
        $"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc
Re: Relocation error with an embedded perl interpreter
by Somni (Friar) on May 13, 2004 at 02:35 UTC

    After further discussion with tigger^ on IRC, and some tinkering, I came up with the following.

    /* gcc -Wall -c perl-embed.c `perl -MExtUtils::Embed -e ccopts` gcc -Wall perl-embed.o `perl -MExtUtils::Embed -e ldopts` -o perl +-embed */ #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; EXTERN_C void xs_init _((pTHX)); EXTERN_C void boot_DynaLoader _((pTHX_ CV* cv)); EXTERN_C void xs_init(pTHX) { dXSUB_SYS; newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); } int main(int argc, char **argv, char **env) { char *embedding[] = { "", "-e" }; SV *my_sv; double (*my_symbol)(double, double); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, xs_init, 3, embedding, (char **)NULL); perl_run(my_perl); my_sv = eval_pv( "use DynaLoader;" "my $h = DynaLoader::dl_load_file(\"libm.so\");" "DynaLoader::dl_find_symbol($h, \"pow\");", TRUE ); my_symbol = (void *)SvIV(my_sv); printf( "Symbol %p, (*my_symbol)(4,4) = %f\n", my_symbol, (*my_symbol)(4,4) ); perl_destruct(my_perl); perl_free(my_perl); return 0; }

    Note, I'm using the standard C function pow() as a stand-in for the original PmmNodeToSv. The important part is that the library is loaded and the symbol retrieved using DynaLoader.

    The problem with this solution is that it uses a specifically unspecified feature of DynaLoader. The documentation specifically states the symbol returned by dl_find_symbol() or dl_find_symbol_anywhere() should only be used in a call to dl_install_xsub(), you should not rely on it for anything else.

    The alternative to this approach seems even less portable though, namely to find the library (auto/XML/LibXML.so) in @INC, dlopen() it, then fetch the symbol with dlsym(). At least with the DynaLoader method you get some level of abstraction between operating systems.

    Are there any alternatives to these methods? How portable is using the symbol returned by DynaLoader, really? From my reading of the source (ext/DynaLoader/dl_*.xs) it seems like this method should work on every OS. Perhaps the documentation is simply leaving a window open for later changes.

    update: removed extraneous include of dlfcn.h, a leftover from earlier attempts at a solution.