这是我的第一个问题。到目前为止,我通过其他问题得到了很多答案,但现在没有更多答案了。
我的工作目标是使用已开发的通信模块堆栈(get as .so),这是用C语言编写的。我想将它与python(cython)结合使用,因为所有其他软件已经是这样写的。在创建和测试从cython到c的方向之后,我在最后几天工作,从c到cython like here。堆栈在c函数中对函数进行了event-driffen调用,我希望集成一个cython函数调用来进行日志记录和进一步的数据处理。但两天后我挂断了电话。它不起作用,因为c函数中的initmodulename-functioncall引发了错误。 所以我开发了以下最小的例子来使它工作,cython和c在两个方向上。这是this one的扩展示例。
我有3个文件, the main.c
#include <python3.4/Python.h>
#include "caller.h"
int main() {
Py_Initialize();
initcaller();
call_quack();
Py_Finalize();
return 0;
}
caller.pyx
from quacker import quack
cdef public void call_quack():
quack()
def run():
cdef extern from "main.c":
int main()
main()
和 quacker.py
def quack():
print("Quack!")
目标是导入调用者,启动run()作为函数,调用c函数并调用call_quack()。
编译我使用(这来自主项目):
CC="gcc -std=c99" CFLAGS="-DCPLB_VENDOR_EAG_TARGETSYSTEM_SHLIBSIEC104_ARM_LINUX -O2 -fPIC" IFLAGS="-I/usr/include/python3.4 -lpython3.4" python3.4 setup.py build_ext --inplace
使用setup.py
# setup.py file
import sys
import os
import shutil
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [
Extension("caller",
sources=["caller.pyx",
],
include_dirs=["/usr/include//python3.4"],
extra_compile_args=["-fopenmp", "-O3"],
extra_link_args=["-DSOME_DEFINE_OPT",
"-L./some/extra/dependency/dir/"]
)
]
)
编译和链接期间没有错误。 但是当我启动python3.4并导入调用者时,我收到以下错误
ImportError: /home/rvk/software/test/caller.cpython-34m.so: undefined symbol: initcaller
任何人都可以帮我解决这个问题吗?我从来没有在两个方向上读过关于usind cython和c的任何例子!有可能吗?
我已经检查过cythonized c-File(caller.c) - 有一个initcaller方法,但只适用于PY_MAJOR_VERSION&lt; 3?!
提前多多感谢
修改
我通过删除 main.c 中的PyInitialze,initcaller和PyFinalize - 函数调用来实现它。也许这与问题有关,我已经在pyx中声明了main.c,所以它是编译库的一部分?!不知道泄漏涉及的地方cython user guide
新的main.c:
#include <python3.4/Python.h>
#include "caller.h"
int main() {
call_quack();
return 0;
}
我还将它整合到主项目中。这里面临的挑战是,应该在cython文件中调用函数的c函数是一个回调函数,所以有必要在cython文件中定义函数 with gil
答案 0 :(得分:1)
在caller.pyx
中有
def run():
cdef extern from "main.c":
int main()
main()
通过包含main.c
导致问题,而caller.h
又包含main()
,这是由cython生成的代码意外发生的事情。此外,调用main.c
中定义的cdef extern from "main.c":
可能会在python解释器中发生时遇到麻烦。因此应删除PyInit_modulename()
。
对于python 3.x,它就像initmodule()
,而不是int main()
{
Py_Initialize();
PyInit_caller();
call_quack();
Py_Finalize();
return 0;
}
A instA = new A();
instA.setImage(*image)