2012-02-15 26 views
6

Estoy tratando de replicar el trabajo de Flavian Coelho, linked here. Usó Cython y la Biblioteca Científica Gnu (GSL) para obtener una gran aceleración sobre Python en la generación de números aleatorios. Cuando importo mi código compilado Cython en Python (con el comando import cgibbs), me sale el siguiente error:ImportError de Cython al vincular una biblioteca de C externa

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

Se dará cuenta de que la queja es que el símbolo _gsl_rng_mt19937 no se puede encontrar. La función a la que intento vincularme se llama gsl_rng_mt19937 (sin subrayado inicial), y así es como aparece en mi archivo .pyx. Creo que Cython de alguna manera está causando el problema al agregar ese guion bajo.

Para facilitar la solución de problemas, he eliminado el código y lo he publicado a continuación. Mi sistema es: Mac OSX 10.7 (Lion) ejecutando Python 2.7.2 (32 bits), gcc-4.0 (que utilicé para compilar las bibliotecas GSL en formato de 32 bits), GSL 1.15 y Cython v0.15.1.

Aquí es el contenido del 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) 

El error desaparece si comento hacia fuera la última línea de mi cgibbs.pyx, pero en realidad no puedo utilizar la biblioteca externa ... Cualquier la visión que puede ofrecer es apreciada. ¡Gracias!

Respuesta

4

Gracias a @ChuiTey, descubrí que otool y son las herramientas en la Mac que pueden hacer lo que objdump hace en Linux. Con nm encontré que los guiones bajos principales son parte del nombre del símbolo en la biblioteca libgsl.a.

Una vez que sabía que el enlazador (en mi caso, ld) estaba buscando el nombre correcto, estaba claro que simplemente no estaba buscando en el lugar correcto. Y así es como aprendí que los archivos de encabezado no conocen la ubicación de las bibliotecas a las que enlazan (¡Duh!). Solo necesitaba agregar la opción -lgsl al comando que ejecuta el enlazador (esto requiere que libgsl.a esté en el directorio donde el enlazador busca bibliotecas - en mi máquina, eso es /usr/local/lib)

también tuve que mover libgsl.dylib de /usr/local/lib, ya que fue compilado para una plataforma de 64 bits y estoy usando Python 32 bits..

Debe haber una manera fácil de especificar la opción del vinculador -lgsl al compilar el código de Cython con distutils o un archivo MAKE; por ahora solo estoy ejecutando gcc-4.0 dos veces para compilar y luego vincular el módulo. Mi flujo de trabajo para compilar un módulo Cython desde la línea de comandos bash es:

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 

que produce cgibbs.so, un módulo Cython que puede importarse en Python 2.7.

2

Agregar un carácter de subrayado a las funciones exportadas se conoce como name mangling. En Windows, la convención cdecl agrega un único guión bajo (otras convenciones tienen esquemas más complicados).

Es posible que no haya especificado la convención de llamadas correctamente al construir su biblioteca GSL. Debería poder ver qué nombres se exportan usando objdump.

¿GSL ya no proporciona envolturas SWIG?

+0

No sé de SWIG, aunque debería hacerlo. – Wesley

Cuestiones relacionadas