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.
|