链接外部C库时从Cython导入ImportError

时间:2012-02-15 23:28:48

标签: python c cython gsl

我试图复制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的最后一行,那么错误就会消失,但我实际上无法使用外部库...您可以提供任何有用的见解。谢谢!

3 个答案:

答案 0 :(得分:4)

感谢@ChuiTey,我发现otoolnm是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)。