2012-02-15 7 views
6

Sto tentando di replicare il lavoro di Flavian Coelho, linked here. Ha usato Cython e la Gnu Scientific Library (GSL) per ottenere un'enorme velocità su Python nella generazione di numeri casuali. Quando importo il mio codice Cython compilato in Python (con il comando import cgibbs), ottengo il seguente errore:ImportError da Cython quando si collega una libreria C esterna

ImportError: dlopen(./cgibbs.so, 2): Symbol not found: _gsl_rng_mt19937 
    Referenced from: /Users/wesley/scratch/cython/cgibbs.so 
    Expected in: dynamic lookup 

Si noterà che la denuncia è che il simbolo _gsl_rng_mt19937 non può essere trovato. La funzione a cui sto tentando di collegarmi è chiamata gsl_rng_mt19937 (nessun trattino basso principale), ed è così che appare nel mio file .pyx. Penso che Cython sia in qualche modo causa del problema aggiungendo quel carattere di sottolineatura principale.

Per semplificare la risoluzione dei problemi, ho rimosso il codice e l'ho postato in basso. Il mio sistema è: Mac OSX 10.7 (Lion) con Python 2.7.2 (32-bit), gcc-4.0 (che ho usato per compilare le librerie GSL in formato 32-bit), GSL 1.15 e Cython v0.15.1.

Ecco il contenuto di cgibbs.pyx:

#declaring external GSL functions to be used 
cdef extern from "math.h": 
    double sqrt(double) 

cdef double Sqrt(double n): 
    return sqrt(n) 

cdef extern from "gsl/gsl_rng.h": 
    ctypedef struct gsl_rng_type: 
     pass 
    ctypedef struct gsl_rng: 
     pass 
    gsl_rng_type *gsl_rng_mt19937 
    gsl_rng *gsl_rng_alloc(gsl_rng_type * T) 

cdef extern from "gsl/gsl_randist.h": 
    double gamma "gsl_ran_gamma"(gsl_rng * r,double,double) 
    double gaussian "gsl_ran_gaussian"(gsl_rng * r,double) 


cdef gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937) 

L'errore va via se io commento l'ultima riga del mio cgibbs.pyx, ma poi non può effettivamente utilizzare la libreria esterna ... Qualsiasi l'intuizione che puoi offrire è apprezzata. Grazie!

risposta

4

Grazie a @ChuiTey, ho scoperto che otool e nm sono gli strumenti sul Mac che possono fare ciò che objdump fa su Linux. Con nm ho scoperto che i trattini bassi di sottolineatura fanno parte del nome del simbolo nella libreria libgsl.a.

Una volta saputo che il linker (nel mio caso, ld) cercava il nome giusto, era chiaro che non stava guardando nel posto giusto. Ed è così che ho appreso che i file di intestazione non conoscono la posizione delle librerie a cui collegano (Duh!) Ho solo bisogno di aggiungere l'opzione -lgsl al comando che esegue il linker (ciò richiede che libgsl.a sia nella directory in cui il vostro linker sembra per le biblioteche - sulla mia macchina, che è /usr/local/lib)

ho anche dovuto spostare libgsl.dylib da /usr/local/lib perché è stato compilato per una piattaforma a 64-bit e sto usando 32 bit Python..

Ci deve essere un modo semplice per specificare l'opzione di collegamento -lgsl durante la compilazione del codice Cython con distutils o un makefile; per ora sto solo eseguendo gcc-4.0 due volte per compilare e quindi collegare il modulo. Il mio flusso di lavoro di compilare un modulo Cython dalla riga di comando bash è:

cython cgibbs.pyx 
gcc-4.0 -m32 -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c cgibbs.c -o cgibbs.o 
gcc-4.0 -bundle -undefined dynamic_lookup -lgsl -arch i386 -g cgibbs.o -o cgibbs.so 

che produce cgibbs.so, un modulo Cython che può essere importato in Python 2.7.

2

La preimpostazione di un carattere di sottolineatura alle funzioni esportate è nota come name mangling. Su Windows, la convenzione cdecl aggiunge un singolo trattino basso (le altre convenzioni hanno schemi più complicati).

È possibile che non sia stata specificata correttamente la convenzione di chiamata quando si crea la libreria GSL. Dovresti essere in grado di dare un'occhiata a quali nomi vengono esportati usando objdump.

GSL non fornisce già wrapper SWIG?

+0

Non so da SWIG - forse dovrei, però. – Wesley