the slides from Shmuel Fomberg's presentation about Embedding ...

greenbeansneedlesΛογισμικό & κατασκευή λογ/κού

13 Δεκ 2013 (πριν από 3 χρόνια και 7 μήνες)

53 εμφανίσεις

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

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();

}

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 *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();

}

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/
)