我正在使用Cython将一组C函数包装到模块中。我希望能够将第一个模块插入到后续的基于Cython的项目中,但是当我在python脚本中导入衍生模块时,我遇到了一个“未定义的符号”问题。
考虑以下在不同目录中开发的两个模块的最小工作示例:
# exModA wraps the functions provided in exModAFxn.c
exModA/
__init__.pxd
__init__.py
exModAFxn.c
exModA.pyx
setup.py
# exModB attempts to use the cdef functions from exModA
exModB/
__init__.py
exModB.pyx
setup.py
# The test script attempts to make use of exModB
test.py
。exModA / __ INIT __ PXD:
cdef extern void myCMessage()
。exModA / __ INIT __ PY:
from exModA import *
exModA / exModAFxn.c:
#include <stdio.h>
void myCMessage() { printf( "This is a test!\n" ); }
exModA / exModA.pyx:
cdef extern from "exModAFxn.c" :
void myCMessage()
# Use myCMessage in a python function
def foo() :
myCMessage()
exModA / setup.py:
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(
name = 'exModA',
ext_modules = cythonize( ['exModA/exModA.pyx'] ),
)
exModB / __ INIT __ PY:
from exModB import *
exModB / exModB.pyx:
cimport exModA
# Use a cdef function from exModA in a python function
def bar() :
exModA.myCMessage()
exModB / setup.py:
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(
name = 'exModB',
ext_modules = cythonize( ['exModB/exModB.pyx'] ),
)
编译两个cython模块后调用test.py脚本。
python extModA/setup.py build_ext --inplace
python extModB/setup.py build_ext --inplace
test.py:
import exModA
exModA.foo() # successfully prints message
import exModB # raises ImportError: undefined symbol: myCMessage
exModB.bar() # we never get to this line :(
从exModA.foo函数成功打印消息向我建议myCMessage实际上是可用的,但是在导入exModB时找不到它。我知道如果我将exModA和exModB合并到一个项目中,这个问题就会消失,但我想尽可能避免这种方法 - 我正在尝试为一个C库公开一组通用的包装器,以便在几个不同的项目中使用应用
答案 0 :(得分:3)
我可以通过以下方式让这个工作:
首先,在exModA
文件中指定exModB/setup.py
库进行链接,如下所示:
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext = Extension('exModB/exModB',
sources=['exModB/exModB.pyx'],
libraries=['exModA'],
library_dirs=['/home/MyFolder/exModA'],
runtime_library_dirs=['/home/MyFolder/exModA']
)
setup(name='exModB', ext_modules = cythonize(ext))
(我建议不要指定运行时库目录,而是将exModA.so
移动到库搜索路径上的文件夹中。)
我还必须将exModA.so
重命名为libexModA.so
,以便gcc可以找到它。在构建exModA.so
之后,但在构建exModB.so
之前执行此操作:
python exModA/setup.py build_ext --inplace
cp exModA/exModA.so exModA/libexModA.so
python exModB/setup.py build_ext --inplace
你可能想要调整它,但它应该让你开始。