2012-02-15 14 views
6

Próbuję odtworzyć pracę Flavian Coelho, linked here. Użył Cythona i Biblioteki Naukowej Gnu (GSL), aby uzyskać ogromne przyspieszenie w Pythonie przy generowaniu liczb losowych. Kiedy zaimportować skompilowany kod Cython w Pythonie (poleceniem import cgibbs), pojawia się następujący błąd:ImportError z Cython podczas łączenia zewnętrznej biblioteki C

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

Zauważysz, że skarga jest to, że symbol _gsl_rng_mt19937 nie można znaleźć. Funkcja, do której próbuję się połączyć, nazywa się gsl_rng_mt19937 (bez wiodącego podkreślenia) i tak wygląda w moim pliku .pyx. Myślę, że Cython w jakiś sposób powoduje problem poprzez dodanie tego wiodącego podkreślenia.

W celu ułatwienia rozwiązywania problemów, usunąłem kod i opublikowałem go poniżej. Mój system to: Mac OSX 10.7 (Lion) z uruchomionym Pythonem 2.7.2 (32-bit), gcc-4.0 (z którego korzystałem podczas kompilowania bibliotek GSL w wersji 32-bitowej), GSL 1.15 i Cython v0.15.1.

Oto treść 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) 

Błąd odchodzi gdybym wykomentuj ostatnią linię moich cgibbs.pyx, ale wtedy nie mogę faktycznie korzysta z zewnętrznej biblioteki ... Wszelkie wgląd, który możesz zaoferować, jest doceniany. Dzięki!

Odpowiedz

4

Dzięki @ChuiTey odkryłem, że otool i nm są narzędziami na Macu, które mogą robić to, co robi objdump na Linuksie. Z wersją nm odkryłem, że wiodące podkreślenia są częścią nazwy symbolu w bibliotece libgsl.a.

Kiedyś wiedziałem, że linker (w moim przypadku ld) szukał właściwej nazwy, było jasne, że po prostu nie szukał we właściwym miejscu. I w ten sposób dowiedziałem się, że pliki nagłówkowe nie znają lokalizacji bibliotek, do których się łączą (Duh!) Właśnie musiałem dodać opcję -lgsl do polecenia, które uruchamia linker (wymaga to, aby libgsl.a był w katalogu, w którym Twój linker szuka bibliotek - na moim komputerze, to /usr/local/lib)

miałem też przenieść libgsl.dylib z /usr/local/lib ponieważ został skompilowany dla platformy 64-bitowej i używam 32-bitowe Python..

Musi istnieć łatwy sposób określenia opcji łącznika -lgsl podczas kompilowania kodu Cython za pomocą distutils lub makefile; na razie właśnie uruchamiam gcc-4.0 dwa razy, aby skompilować, a następnie połączyć moduł. Mój workflow skompilować moduł Cython z wiersza poleceń 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 

która produkuje cgibbs.so, moduł Cython, które mogą być importowane w Pythonie 2.7.

2

Przedsprzedaż wyeksportowanych funkcji jest znana jako name mangling. W systemie Windows konwencja cdecl dołącza jedno podkreślenie (inne konwencje mają bardziej skomplikowane schematy).

Możliwe, że nie podałeś poprawnie konwencji wywołującej podczas budowania biblioteki GSL. Powinieneś być w stanie spojrzeć na to, jakie nazwy są eksportowane za pomocą objdump.

Czy GSL nie oferuje już opakowań typu SWIG?

+0

Nie wiem od SWIG - może powinienem jednak. – Wesley

Powiązane problemy