在Cython中包含一个有点大的C库

时间:2015-04-06 22:01:58

标签: python c cython

我是Cython的新手,并且了解C / C ++编译的基础知识。

这是我想要做的事情:

有一个用C编写的相当大的库,我想在我的Python程序中加入。 (特别是它是GNUGo的板逻辑的实现。我正在尝试为它构建AI。)我需要这个例程快,并且使用Python的逻辑实现太慢了

Cython文档说我应该创建一个.pxd文件,列出从.h文件外部定义的方法签名。然后我应该在相应的.pyx文件中创建一个包装类,并手动创建挂钩到上面列出的方法签名的Python端函数调用。

我遇到的问题是我想要实现的库不是像文档示例那样的单个C文件。它使用多个C文件,它们各有相互依赖关系,游戏板表示为一组全局变量,它们在整个地方定义为extern。我真的,真的不想为所有必需的C文件写.pxd

GNUGo文档表明我可以创建一个libboard.a文件 - 这在概念上与.o文件不同,有没有办法将此文件包含在Cython中?理想情况下,我希望将其视为黑盒子,让我进行方法调用,让库处理其疯狂的全局变量,并返回所需的输出。

1 个答案:

答案 0 :(得分:0)

我不确定这是否是正确的"这样做的方法,但这就是我如何使它发挥作用。

在我的go.pxd文件中,我从头文件board.h列出了我需要的所有方法声明。而不是做

cdef extern from "board.h":
    ...

我做

cdef extern:
    ...

因为我不想实际包含board.h文件 - 我改为使用库libboard.a。在该块中,我列出了我需要的所有方法。

在我的go.pyx文件中,我cimport go,然后在我需要使用它时执行go.method_name(args)。在go.pyx上运行Cython以生成go.c工作文件,因为所有方法都已定义extern

最后,要将其转换为要导入的go.so库,我有一个基本上做的Makefile

gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing \
  -I/usr/include/python2.7 go.c libboard.a -o go.so

最终的go.so可以在Python中导入并且工作正常。

棘手的部分是我需要在链接之前用libboard.a重新编译-fPIC。我还需要删除一些curses.h / term.h的库调用,因为我无法使这些包含工作,但幸运的是我还不需要漂亮的打印。

一般情况下,您似乎应该能够在最后一步中链接任意.o.a声明,只要您不指定它们的位置{{1}来自extern文件。这似乎很快就会变得非常混乱,但至少它是有效的。