6

我正在尝试复制 Flavian Coelho 的作品,链接在这里。他使用 Cython 和 Gnu Scientific Library (GSL) 在生成随机数方面比 Python 获得了巨大的加速。当我在 Python 中导入已编译的 Cython 代码时(使用 command 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 通过添加前导下划线以某种方式引起了问题。

为了使故障排除更容易,我已经剥离了代码并将其发布在下面。我的系统是:运行 Python 2.7.2(32 位)的 Mac OSX 10.7(Lion)、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)

如果我注释掉我的最后一行,错误就会消失cgibbs.pyx,但是我实际上不能使用外部库......您可以提供的任何见解都将受到赞赏。谢谢!

4

3 回答 3

4

感谢@ChuiTey,我发现了这一点,otool并且nm这些工具在 Mac 上可以做 objdump 在 Linux 上做的事情。我nm发现前导下划线是libgsl.a库中符号名称的一部分。

一旦我知道链接器(在我的例子中,ld)正在寻找正确的名称,很明显它只是没有在正确的地方寻找。这就是我了解到头文件不知道它们链接到的库的位置的方式(Duh!)我只需要将选项添加-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

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

于 2012-02-16T02:44:18.257 回答
2

为导出的函数添加下划线称为名称修饰。在 Windows 上, cdecl 约定附加一个下划线(其他约定有更复杂的方案)。

可能是您在构建 GSL 库时没有正确指定调用约定。您应该能够查看使用objdump导出的名称。

GSL 不是已经提供 SWIG 包装器了吗?

于 2012-02-16T00:01:55.073 回答
0

当您想在 Cython 中使用 GSL 功能时,请查看 CythonGSL ( https://github.com/twiecki/CythonGSL )。

于 2013-03-27T19:55:47.250 回答