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

is there a way to call c subroutines from an in c embedded perl interpreter? (i have 2 concurrent c threads both running a perl interpreter and i want them to talk through a mutex)

Replies are listed 'Best First'.
Re: embedded perl calls c subroutines
by Courage (Parson) on Aug 11, 2002 at 17:48 UTC
    In a correct way, you do this using .xs file, which then will be translated to c during make build process (xsubpp does the real translation). That *.xs file is actually a wrapper to your c file nad/or library.

    There are some less "strict" ways to declare subroutines from C to make Perl to be able to use them, but I'll not say to you how to do that, because you'll shoot your leg...
    (let me know if I should share my "easier" but not-supported experience with you)

    Courage, the Cowardly Dog

      Inline::C is a very happy thing, BTW. (However, Inline::C just uses the same ol' XS itself; it's just an easier way of writing it.)


      Confession: It does an Immortal Body good.

        Inline::C is an excellent thing to start, and very interesting, and many other good words we'll say to it.

        But (IMHO) sometimes it's may be not good to use it in a final version of a script, because it recompiles something on the fly, and that means not only big startup time of a script, but also you must distribute your program with C compiler.

        addition: After some experiments, I found out that I was wrong and things are easier to end-user than I thought: once Inline::C compiled a code, it do not recompile it again, and just loads it on demand from a single dll file (on my Win32).
        Very interesting module to play with!

        Courage, the Cowardly Dog

      yeah plaese tell me about the less "strict" way. i want to play around anyway ... but i'm going in circles, i tried h2xs and swig already, but get a) problems with dynaloader (I DON'T want dynamic loading anyway ;-) and b) segmentation faults ...

      BTW: Inline::C is not what i'm looking for. the c-subroutine is already compiled with the c program that starts the perl interpreter. i used Inline::C in other projects it's quite nice and it does caching of compiled code.

        Do not afraid to shoot your leg? You're brave man!

        I did "glueing" that way: (nothing unusual, I just read perlembed and related documentation)

        1. #include <EXTERN.h>, #include <perl.h> somewhere at the very top of C program. #include "xsub.h" somewhere near the end, and after that all "glue" functions are placed. All those header files are in perl/lib/CORE/* directory.
        2. Write "glue" functions like following example:
          XS(TStringsTIEARRAY) { dXSARGS; SV *ssv=ST(0); // "G::TStrings" void* tmp[4]; memset(tmp,0,sizeof(tmp)); tmp[2] = 0; ((TStrings*)(tmp[0])) = TyingStrings; ((TComponent*)(tmp[1])) = TyingComp; ((int)(tmp[2])) = TyingOpt; SV *tsv; tsv = newSVpv((char*)&tmp[0],16); STRLEN len; char *ptr = SvPV(ssv,len); HV *stash = gv_stashpvn(ptr,len, TRUE); SV *rsv = newRV_inc(tsv); sv_bless(rsv,stash); ST(0) = rsv; XSRETURN(1); }
          Note usage of XS macro, "real" name of function will be more complicated after expansion of that macro.
        3. initialize your perl instance(s) as perlembed.pod says you to.
        4. After initializing it/them, in order to make those functions visible to perl, do something like:
          newXS("G::TStrings::TIEARRAY", TStringsTIEARRAY, "BCB+Perl interna +l");
        5. you may want to also run following:
          newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, "blablabla") +;
          to enable dynamic loading of modules.
        And remember, I do not enCourage you to do that :)

        Courage, the Cowardly Dog
        things, I do for love to perl...