Python 链接外部C库时从Cython导入错误
我试图复制弗拉维安·科埃略的作品。他使用Cython和Gnu科学库(GSL)在生成随机数方面比Python有了巨大的速度。当我在Python中导入已编译的Cython代码时(使用命令Python 链接外部C库时从Cython导入错误,python,c,cython,gsl,Python,C,Cython,Gsl,我试图复制弗拉维安·科埃略的作品。他使用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 E
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
您会注意到投诉是找不到符号\u gsl\u rng\u mt19937
。我试图链接到的函数名为gsl\u rng\u mt19937
(无前导下划线),这就是它在我的.pyx
文件中的显示方式。我认为Cython添加了那条主要的下划线,不知何故造成了这个问题
为了使故障排除更容易,我将代码剥离并发布在下面。我的系统是:MacOSX10.7(Lion),运行Python 2.7.2(32位)、gcc-4.0(我用它以32位的形式编译GSL库)、GSL1.15和CythonV0.15.1
以下是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
的最后一行,错误就会消失,但是我实际上无法使用外部库。。。感谢您提供的任何见解。谢谢 在导出函数前加下划线称为。在Windows上,cdecl约定附加一个下划线(其他约定有更复杂的方案)
可能是您在构建GSL库时没有正确指定调用约定。您应该能够查看使用导出的名称
GSL不是已经提供SWIG包装了吗?多亏了@ChuiTey,我发现Mac上的
otool
和nm
工具可以完成objdump在Linux上的功能。在nm
中,我发现前导下划线是libgsl.a
库中符号名称的一部分
一旦我知道链接器(在我的例子中,ld
)正在寻找正确的名称,很明显它找不到正确的位置。这就是为什么我知道头文件不知道它们链接到的库的位置(Duh!)我只需要在运行链接器的命令中添加选项-lgsl
(这要求libgsl.a
位于链接器查找库的目录中-在我的机器上,即/usr/local/lib
)
我还必须从/usr/local/lib
中移动libgsl.dylib
,因为它是为64位平台编译的,我使用的是32位Python
在使用distutils或makefile编译Cython代码时,必须有一种简单的方法来指定-lgsl
链接器选项;现在我只运行两次gcc-4.0来编译并链接模块。我从bash命令行编译Cython模块的工作流是:
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
它产生了
cgibbs.so
,一个可以在Python 2.7中导入的Cython模块。当你想在Cython中使用GSL函数时,请看一下CythonGSL()。我不知道来自SWIG-也许我应该这样做。