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

Wes*_*ley 6 c python cython gsl

我试图复制Flavian Coelho的作品,链接在这里.他使用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
Run Code Online (Sandbox Code Playgroud)

您会注意到投诉是_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.

这是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)
Run Code Online (Sandbox Code Playgroud)

如果我注释掉我的最后一行cgibbs.pyx,那么错误就会消失,但实际上我无法使用外部库...您可以提供任何洞察力.谢谢!

Wes*_*ley 4

感谢@ChuiTey,我发现otoolnm是 Mac 上可以完成 objdump 在 Linux 上所做的事情的工具。我发现nm前导下划线是符号名称的一部分libgsl.a库中符号名称的一部分。

一旦我知道链接器(在我的例子中,ld)正在寻找正确的名称,很明显它只是没有在正确的位置寻找。这就是我了解到头文件不知道它们链接到的库的位置(废话!)我只需要将选项添加到-lgsl运行链接器的命令中(这需要libgsl.a位于链接器所在的目录中)寻找库 - 在我的机器上,那就是/usr/local/lib。)

我还必须放弃libgsl.dylib它,/usr/local/lib因为它是为 64 位平台编译的,而我使用的是 32 位 Python。

-lgsl使用 distutils 或 makefile 编译 Cython 代码时,必须有一种简单的方法来指定链接器选项;现在我只是运行 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
Run Code Online (Sandbox Code Playgroud)

它生成cgibbs.so,一个可以在 Python 2.7 中导入的 Cython 模块。