160 likes | 242 Views
PerlGuts->PerlEmbed->PerlCall. Calling Perl from your C program. PerlGuts. SV – the basic variable AV – Array HV – Hash STASH – Package / Namespace. PerlGuts. PerlAPI. newSV, newSVpv, newSViv …. sv_setpv/iv/nv Sv(Flag): SvCUR, SvIOK, SvPOK …. SvIV, SvPV
E N D
PerlGuts->PerlEmbed->PerlCall Calling Perl from your C program
PerlGuts SV – the basic variable AV – Array HV – Hash STASH – Package / Namespace
PerlAPI newSV, newSVpv, newSViv …. sv_setpv/iv/nv Sv(Flag): SvCUR, SvIOK, SvPOK …. SvIV, SvPV SvREFCNT, SvREFCNT_inc, SvREFCNT_dec newAV, av_pop, av_unshift, av_fetch newHV, hv_store, hv_fetch Total: 400 API functions + tons of macros
PerlGuts – other concepts • Mortal variables • sv_2mortal • Perl Stack • @_
PerlEmbed A Simple Embedded Perl: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, argc, argv, (char **)NULL); perl_run(my_perl); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { PERL_SYS_INIT3(&argc,&argv,&env); char *my_argv[] = { "", "power.pl" }; my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); } A Simple Embedded Perl:
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { PERL_SYS_INIT3(&argc,&argv,&env); char *embedding[] = { "", "-e", "0" }; my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; eval_pv(“my $a=5; print $a x 3;”, FALSE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); } A Simple Embedded Perl:
Conventions • d – define / declare • a – argument • p – parameter • _ - there should be a comma after Example: aTHX_
#include <EXTERN.h> #include <perl.h> int main(int argc, char **argv, char **env) { PERL_SYS_INIT3(&argc,&argv,&env); char *embedding[] = { "", "power.pl" }; PerlInterpreter *perl_inter; perl_inter = perl_alloc(); perl_construct(perl_inter); dTHXa(perl_inter); perl_parse(perl_inter, NULL, 2, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; char *name = “MyPackage”; load_module(PERL_LOADMOD_NOIMPORT, newSVpvn(name, strlen(name)), Nullsv); call_func(aTHX_ 7, 5); perl_destruct(perl_inter); perl_free(perl_inter); PERL_SYS_TERM(); }
If my function is: sub Multiply { print $_[0]*$_[1] } void call_func(pTHX_ int x, int y) { dSP; char *params[] = {“5”, “7”, NULL}; call_argv(“Multiply”, G_DISCARD, params); } Flags: G_VOID, G_SCALAR, G_ARRAY, G_DISCARD, G_NOARGS, G_EVAL, G_KEEPERR
void call_func(pTHX_ int x, int y) { dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(x))); XPUSHs(sv_2mortal(newSViv(y))); PUTBACK; call_pv("Multiply", G_DISCARD); FREETMPS; LEAVE; } Now let’s add two more functions: sub Multiply2 { return $_[0]*$_[1] } sub some_calcs { return ($_[0]+$_[1], $_[0]-$[1]) }
int call_func(pTHX_ int x, int y) { dSP; int count; int ret = -1; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(x))); XPUSHs(sv_2mortal(newSViv(y))); PUTBACK; count = call_pv("Multiply2", G_SCALAR | G_EVAL); SPAGAIN; if (SvTRUE(ERRSV)) { // There was an error char *err_str = SvPVX(ERRSV); POPs; } else { ret = POPi; } FREETMPS; LEAVE; return ret; } Always, even if there was an exception, pop a value off the stack
int call_func(pTHX_ int x, int y) { ... count = call_pv(“some_calcs", G_ARRAY | G_EVAL); SPAGAIN; // count – can be 0 (exception, empty list) // One way to access the returned values is with the // POPx macros – but will receive results in reverse // order. Other way: (should include xsub.h) I32 ax; SP -= count; ax = (SP - PL_stack_base) + 1; // And then: printf(“Added: %d, Substracted: %d\n”, SvIV(ST(0)), SvIV(ST(1))); ... }
Dynamic Loader EXTERN_C void boot_DynaLoader (pTHX_ CV* cv); EXTERN_C void xs_init(pTHX) { char *file = __FILE__; dXSUB_SYS; /* DynaLoader is a special case */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); } And then: perl_parse(perl_inter, xs_init, 3, my_argv, (char **)NULL);
Sources Perldoc: perlhack, perlguts, perlembed, perlcall, perlapi PerlGuts Illustrated (http://gisle.aas.no/perl/illguts/)