2010-10-29 10 views
12

Ok, questa è una domanda molto interessante e potrebbe non esserci un modo semplice per farlo, ma ho pensato di buttarla lì prima di decidere che la modifica di Perl è la mia risposta di fondo.Chiamare la funzione C da Perl all'interno dell'applicazione C incorporata

Quindi ho un'applicazione C che chiama gli script Perl in modo incorporato. Tutto questo funziona bene e dandy ed è fantastico che io possa passare informazioni e ottenere informazioni indietro. TUTTAVIA, ora alla mia prossima conquista; Devo consentire al mio script incorporato di essere in grado di chiamare alcune funzioni all'interno dell'applicazione C che ORIGINALMENTE CHIAMATO.

Questo è importante perché XSUB richiederebbe che fosse una libreria esterna; ma non voglio che sia una libreria esterna, voglio che sia una chiamata diretta alle funzioni C. Ora forse questo può essere fatto tramite XSUB e ho appena letto e capito male.

Application -(run)-> Perl 

Application <-(function_x())- Perl 

Application -(returnfunction_x)-> Perl 

La ragione per cui questo non può essere una libreria esterna è perché sto facendo riferimento ai dati che si crea solo/memorizzati all'interno dell'applicazione.

+0

Il modo per farlo in Python è quello di creare una funzione FFI in C e quindi aggiungere al dizionario di un modulo virtuale che le importazioni di script Python. Non sono sicuro che sia fatto allo stesso modo in Perl. –

risposta

7

Gli XSUB in realtà non richiedono che ci sia una libreria esterna. Forniscono semplicemente la possibilità di chiamare una funzione c da perl space e forniscono una certa comodità nel mappare le convenzioni di chiamata tra C e Perl.

Tutto quello che dovete fare è registrarsi XSUB è stato compilato nell'applicazione embedding con l'interprete Perl che stai incorporamento.

#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__); 

Quando l'inclusione del Perl, questo genere di cose di solito è fatto nella funzione xs_init si passa a 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); 

Dopo che sarete in grado di chiamare alla XSUB come Some::Perl::function dallo spazio perl, e che XSUB a sua volta è libero di richiamare alla vostra applicazione in alcun modo che vuole.

+0

Quindi la prima sezione incollata si trova in un file .xs? – Suroot

+0

E 'codice C, quindi avrei voluto metterlo in un file '.c', ma dubito qualsiasi compilatore C adeguato si preoccupa per l'estensione dei file che chiediamo di compilare :-) – rafl

+1

Tutto ha un senso ora; Stavo pensando che la roba newXS era in realtà solo parlando di caricamento dei moduli. Impossibile trovare molta documentazione su Perl-XS; il più apprezzato signore! – Suroot