2014-12-17 13 views
5

Sto cercando di creare un semplice wrapper attorno alla libreria C utilizzando Inline::C. Ho installato libcmark.so in /usr/local/lib/.Funzione di chiamata nella libreria C in linea

mio codice attuale è simile al seguente:

package Text::CommonMark; 

use strict; 
use warnings; 

sub commonmarker { 
    my $text = shift; 
    return commonmark_to_html($text); 
} 

use Inline C => qq{ 

    char* commonmark_to_html(char* thetext) { 

     char* result = cmark_markdown_to_html(thetext, strlen(thetext)); 
     return result; 
    } 
} => LIBS => '-L/usr/local/lib/ -llibcmark.so'; 

1; 

Quando si utilizza commonmarker da uno script ottengo:

perl: symbol lookup error: /home/erik/sublimeworks/dists/Text-CommonMark/_Inline/lib/auto/Text/CommonMark_33fb/CommonMark_33fb.so: undefined symbol: cmark_markdown_to_html 

presumo che la mia chiamata a cmark_markdown_to_html non corrisponde la sua firma, ma tutti firme per cmark_markdown_to_html che ho found:

char *cmark_markdown_to_html(const char *text, int len) 

Non ho ancora toccato C o Inline :: C, quindi probabilmente mi manca qualcosa.

+1

Tip: Utilizzo di 'q {}' invece di 'qq {}' si intende devono scappare molto meno. Meglio ancora, usare "<< EOC" significa che non devi scappare di niente. – ikegami

+1

Non penso che sia un prototipo non corrispondente. Penso che il simbolo non si trova nella libreria, o la libreria stessa non viene trovata. 'perl -MInline = force, info, noclean script.pl' potrebbe fornire maggiori informazioni. – ikegami

risposta

4

Non citato in LIBS nei documenti. L'opzione è denominata libs.

use Inline C => config => libs => '-L/usr/local/lib/ -llibcmark.so'; 
use Inline C => <<'__EOC__'; 

    char* commonmark_to_html(char* thetext) { 
     char* result = cmark_markdown_to_html(thetext, strlen(thetext)); 
     return result; 
    } 

__EOC__ 

noti che usare char* thetext come argomento a una funzione XS è un segno sicuro di un bug. Questo ti dà un puntatore al buffer della stringa senza dirti il ​​formato del buffer.

Supponendo biblioteca accetta e ritorna testo codificato con UTF-8,

SV* commonmark_to_html(SV* text_sv) { 
    STRLEN text_len; 
    const char* text = SvPVutf8(text_sv, text_len); 
    const char* html = cmark_markdown_to_html(text, text_len); 
    SV* html_sv = newSVpvn_flags(html, strlen(html), SVf_UTF8); 
    free(html); 
    return html_sv; 
} 

ottimizzato leggermente (dal avente newSVpvn_flags mortalize scalare è più efficiente che avere il codice di chiamata typemap generato sv_2mortal):

void commonmark_to_html(SV* text_sv) { 
    STRLEN text_len; 
    const char* text = SvPVutf8(text_sv, text_len); 
    const char* html = cmark_markdown_to_html(text, text_len); 
    SV* html_sv = newSVpvn_flags(html, strlen(html), SVf_UTF8|SVs_TEMP); 
    free(html); 
    ST(0) = html_sv; 
    XSRETURN(1); 
} 
+0

Grazie! Sto indovinando che dovrebbe essere: ... => config => librerie => ... ('utilizzo non valido di modulo Inline' senza la 'librerie =>') ancora trovato la stesso errore però. Ho ricevuto la 'LIBS' da Inline :: C :: Cookbook. – Csson

+1

@Csson, Oops, sì, corretto. Bene, allora la libreria non contiene il simbolo 'cmark_markdown_to_html', o non può trovare la libreria. Quest'ultimo dovrebbe far apparire un avvertimento per 'perl -MInline = force, info, noclean script.pl'. – ikegami

+0

Grazie, funziona bene! – Csson

2

L'argomento -l sembra sospetto. Di solito il compilatore/linker prefisso il "lib" e il suffisso del ".so", così normalmente si dovrebbe solo bisogno di fornire

-lcmark 
+0

In effetti funziona in entrambi i modi, ma è bello saperlo. Grazie! – Csson

Problemi correlati