Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

embedded perl: C-Perl-C

by daveola (Sexton)
on Sep 21, 2001 at 04:30 UTC ( [id://113757]=perlquestion: print w/replies, xml ) Need Help??

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

I'm trying to connect perl and C together. I know how to call perl from C code, by creating a new PerlInterpreter.

I've also played with calling C from perl code, by creating xsubs.

But what I really want to do is call perl from C, and then from that perl, call functions back in the original C, but more importantly I need to make this a library that I can link in with a C program.

In other words, I need to be able to do something like this:

C CODE: int some_Cvar; // Global to C int main (void) { call_perl("some_perl_func"); printf("C: some_Cvar = %d\n",some_Cvar); } int set_some_Cvar (int val) { some_Cvar = val; } ------------------------- PERL CODE: sub some_perl_func { print "In perl - setting some_Cvar\n"; set_some_Cvar(42); }
And most importantly I need to be able to do it as a library, since I'm linking it with a program that I don't have the source for... (don't ask :)

Replies are listed 'Best First'.
Re: embedded perl: C-Perl-C
by ducky (Scribe) on Sep 21, 2001 at 05:10 UTC
      No this won't accomplish the example I gave in the original post. I need to:

      1) Start with C main (so, it needs to be a perl library, not a modified perl)
      2) Call perl from C
      3) From inside the perl subroutine, call a C function in the same namespace as the C main()

      This is what I'm looking for. I'm beginning to think it can't currently be done because it would be too difficult to manage the stack, and probably nobody has needed it since most are happy with Inline, XS or perl_call.

Re: embedded perl: C-Perl-C
by wog (Curate) on Sep 21, 2001 at 05:08 UTC
    To allow your embedded code to have callbacks from perl, you can compile .xs file(s) having XS functions doing the desired tasks. Your C library would create the bootstrap function for your module (like done in the example xs_init function in perlembed) and call the bootstrap method for the XS module (a task ordinarily be done by a .pm file, which if may be a better place to put this if you provide real .pm files somehow). If you do not want to divide your code into perl embedding files and perl XS files, you can put most of your non-XS code at the top of the .xs file(s) before the MODULE = line.

    You may find it helpful to look at the perl embeding portions of a program that embeds perl like this, for example, VIM (which I used to derive some of this information.)

      If I'm not mistaken, then I can compile C code into perl that I can call from perl. But that doesn't quite solve my problem - because it won't allow me to call the C functions that started up the perl interpretor in the first place, will it? It just calls the C functions that were compiled into the perl library - right? Take a look at the example pseudo-code I want to be able to do - I want to call a function in the original C code that alters state inside that space.
        I was referring to setting up XS within perl embedded in C. This XS would handle your callbacks from perl. To give an example which should clarify things somewhat, here's an an xs file with perl embedding built-in:

        #include <stdio.h> #include "EXTERN.h" #include "perl.h" #include "XSUB.h" static PerlInterpreter* my_perl; static int my_c_var; static void xs_init(pTHX); extern void boot_DynaLoader(pTHX_ CV* cv); void boot_Example (pTHX_ CV* cv); static void xs_init(pTHX) { /* set us up for dynamicly loaded modules */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); /* setup our module included in this file */ newXS("Example::bootstrap", boot_Example, __FILE__); } static void init_our_modules() { static const char* bootstrap_args[] = { "Example", NULL }; /* equivilent to bootstrap Example; pretty much */ call_argv("Example::bootstrap", G_DISCARD, bootstrap_args); } /* main function. In a library you'd probably use a different callback and do this in multiple functions, but I think you can get the idea. */ int main(int argc, char** argv, char** env) { /* same fake args for perl_parse */ /* we turn on warnings by default here. 'cuz they're good. */ static const char* perl_argv[] = { "", "-w", "-e", "0" }; my_c_var = 1; my_perl = perl_alloc(); perl_construct(my_perl); /* just to initiaize it */ perl_parse(my_perl, xs_init, 4, perl_argv, NULL); /* run END blocks in perl_destruct */ PL_exit_flags |= PERL_EXIT_DESTRUCT_END; init_our_modules(); puts("Perl seems to be initialized.\n"); printf("my_c_var = %d\n", my_c_var); eval_pv( /* Hey, perl programs in C code! */ "use strict;\n" "$\\ = qq[\\n];\n" "print q[get_my_c_var() = ], Example::get_my_c_var();\n" "Example::set_my_c_var(42);\n" "print q[get_my_c_var() = ], Example::get_my_c_var();\n" , TRUE); printf("my_c_var = %d\n", my_c_var); perl_destruct(my_perl); perl_free(my_perl); } /* And some XS code. */ MODULE = Example PACKAGE = Example int get_my_c_var() CODE: RETVAL = my_c_var; OUTPUT: RETVAL void set_my_c_var(newval) int newval CODE: my_c_var = newval;

        On my system I can compile this by first generating a .c file with:

        perl `perl -MConfig -le 'print $Config{privlibexp}'`/ExtUtils/xsubpp - +prototypes -typemap `perl -MConfig -le 'print $Config{privlibexp}'`/E +xtUtils/typemap Example.xs > example.c

        (I copy this strategy from what vim appears, though it would probably be better to do this by going through the work of extracting it from a Makefile.PL created Makefile.)

        This I compiled it with:

        `perl -MConfig -e 'print $Config{cc}'` -o example example.c `perl -MEx +tUtils::Embed -e ccopts -e ldopts`

        (This, for some reason gave two warnings about incompatible pointer type casts, which didn't seem to cause a problem.)

        Running the resulting program reveals:

        Perl seems to be initialized. my_c_var = 1 get_my_c_var() = 1 get_my_c_var() = 42 my_c_var = 42

        Hope this can be of some help.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://113757]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (2)
As of 2024-04-25 20:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found