tags:

views:

55

answers:

1

Ok, this is a very interesting question and there may not be any easy way to do this but figured I would throw this out there before deciding that modifying Perl is my underlying answer.

So I've got a C application that calls Perl scripts in an embedded fashion. This all works fine and dandy and it's pretty awesome that I can pass information in and get information back out. HOWEVER, now onto my next conquest; I need to allow my embedded script(s) to be able to call some functions within the C application that ORIGINALLY CALLED IT.

This is important because XSUB would require it to be an external library; but I don't want it to be an external library I want it to be a direct call to the C function(s). Now maybe this can be done via XSUB and I've just been reading and understanding it wrong.

Application -(run)-> Perl

Application <-(function_x())- Perl

Application -(returnfunction_x)-> Perl

The reason this cannot be an external library is because I am relying on data that is solely created/stored within the application.

+3  A: 

XSUBs actually don't require there to be an external library. They merely provide the ability to call to a c function from perl space, and provide some convenience in mapping the calling conventions between C and Perl.

All you need to do is register XSUBs you compiled into the embedding application with the perl interpreter you're embedding.

#include "XSUB.h"

XS(XS_some_func);
XS(XS_some_func)
{
    dXSARGS;
    char *str_from_perl, *str_from_c;

    /* get SV*s from the stack usign ST(x) and friends, do stuff to them */
    str_from_perl = SvPV_nolen(ST(0));

    /* do your c thing calling back to your application, or whatever */
    str_from_c = some_c_func(str_from_perl);

    /* pack up the c retval into an sv again and return it on the stack */
    mXPUSHp(c_str);
    XSRETURN(1);
}

/* register the above XSUB with the perl interpreter after creating it */
newXS("Some::Perl::function", XS_some_func, __FILE__);

When embedding perl, this sort of thing is usually done in the xs_init function you pass to parse_perl.

EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);

static void
xs_init (pTHX)
{
    newXS("Some::Perl::function", XS_some_func, __FILE__);
    /* possibly also boot DynaLoader and friends. perlembed has more
     * details on this, and ExtUtils::Embed helps as well. */
    newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}

perl_parse(my_perl, xs_init, argc, my_argv, NULL);

After that you'll be able to call to the XSUB as Some::Perl::function from perl space, and that XSUB in turn is free to call back to your application in any way it wants to.

rafl
So does the first section that you pasted go into an .xs file?
Suroot
It's C code, so I'd want to put it in a `.c` file, but I doubt any proper C compiler cares about the extension of the files you ask it to compile :-)
rafl
It all makes sense now; I was thinking that the newXS stuff was actually just talking about loading modules. Couldn't find much documentation about perl-xs; most appreciated sir!
Suroot