2013-06-05 7 views
8

Sono piuttosto un principiante XS e sto cercando di cambiare un modulo XS esistente che usa pesantemente una libreria C sottostante di 15 anni (in effetti il ​​modulo è fondamentalmente solo colla questa libreria). Il problema è che mi piacerebbe essere in grado di utilizzare PerlIO stringa di inganno come:Fare una vecchia libreria funziona con Perl XS e PerlIO

open($fh, '<', \$string); 

e quindi passare $fh alla colla XS in cui la libreria si aspetta FILE. Il problema è che la XS ha:

int 
_parse (entry_ref, filename, file, preserve=FALSE) 
    SV * entry_ref; 
    char * filename; 
    FILE * file; 
    boolean preserve; 

e presumo che ha bisogno di essere:

PerlIO * file; 

Questo non funziona, naturalmente, come ci deve essere qualcosa di più quello. Quando guardo il codice _parse in biblioteca, finisce in:

AST * bt_parse_entry (FILE * infile, 
         char * filename, 
         btshort options, 
         boolean * status) 
{ 
    AST *   entry_ast = NULL; 
    static int * err_counts = NULL; 
    static FILE * prev_file = NULL; 

con FILE tipi di nuovo. Ora la domanda di base che devo iniziare è - è anche possibile senza cambiare la libreria; cioè, posso ottenere pseudo-filehandle dal comportamento delle stringhe PerlIO cambiando semplicemente l'XS?

risposta

3

L'API Perl fornisce PerlIO_exportFILE() (Implementation) che può convertire un handle PerlIO con un descrittore di file in un puntatore stdio FILE. Poiché PerlIO::Scalar è un handle di file "in memoria" senza descrittore di file, la conversione non può avere esito positivo. L'unico metodo portatile per passare un handle PerlIO::Scalar consiste nel scaricarlo in un file temporaneo. Il modo meno portabile sarebbe utilizzare uno stdio che supporti i callback, come l'implementazione BSD, funopen(3).