我试图复制Flavian Coelho的作品,linked here。他使用Cython和Gnu科学库(GSL)在生成随机数时大大加快了Python的速度。当我在Python中导入我编译的Cython代码时(使用命令import cgibbs
),我收到以下错误:
ImportError: dlopen(./cgibbs.so, 2): Symbol not found: _gsl_rng_mt19937
Referenced from: /Users/wesley/scratch/cython/cgibbs.so
Expected in: dynamic lookup
您会注意到投诉是无法找到符号_gsl_rng_mt19937
。我尝试链接的函数称为gsl_rng_mt19937
(没有前导下划线),这就是它在.pyx
文件中的显示方式。我认为Cython通过添加前导下划线以某种方式导致问题。
为了简化故障排除,我删除了代码并将其发布在下面。我的系统是:Mac OSX 10.7(Lion)运行Python 2.7.2(32位),gcc-4.0(我用它来编译32位形式的GSL库),GSL 1.15和Cython v0.15.1。 / p>
以下是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)
如果我注释掉cgibbs.pyx
的最后一行,那么错误就会消失,但我实际上无法使用外部库...您可以提供任何有用的见解。谢谢!
答案 0 :(得分:4)
感谢@ChuiTey,我发现otool
和nm
是Mac上可以执行objdump在Linux上执行操作的工具。使用nm
,我发现前导下划线是libgsl.a
库中符号名称的一部分。
一旦我知道链接器(在我的情况下,ld
)正在寻找正确的名称,很明显它只是没有找到正确的位置。这就是我学习头文件不知道它们所链接的库的位置的原因(Duh!)我只需要将-lgsl
选项添加到运行链接器的命令中(这需要{{} 1}}位于链接器查找库的目录中 - 在我的机器上,即libgsl.a
。)
我还必须从/usr/local/lib
移动libgsl.dylib
,因为它是为64位平台编译的,我使用的是32位Python。
在使用distutils或makefile编译Cython代码时,必须有一种简单的方法来指定/usr/local/lib
链接器选项;现在我只是运行gcc-4.0两次编译然后链接模块。我从bash命令行编译Cython模块的工作流程是:
-lgsl
产生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
,一个可以在Python 2.7中导入的Cython模块。
答案 1 :(得分:2)
在导出的函数前加下划线称为name mangling。在Windows上,cdecl约定附加一个下划线(其他约定具有更复杂的方案)。
在构建GSL库时,可能没有正确指定调用约定。您应该能够使用objdump查看导出的名称。
GSL是否已提供SWIG包装?
答案 2 :(得分:0)
如果您想在Cython中使用GSL函数,请查看CythonGSL(https://github.com/twiecki/CythonGSL)。