Python 用cython调用C代码,并从C调用cython代码

Python 用cython调用C代码,并从C调用cython代码,python,cython,Python,Cython,这是我的第一个问题。到目前为止,我通过其他问题得到了很多答案,但现在没有更多的答案了 我工作的目的是使用一个用C编写的通信模块(get as.so)的开发堆栈。我想将它与python(cython)结合起来,因为所有其他软件都是这样编写的。在创建并测试了从cython到c的方向之后,我在最后几天为从c到cython的方向工作。堆栈对c函数中的函数进行了事件driffen调用,我想集成对cython函数的调用,用于日志记录和进一步的数据处理。但两天后我挂了电话。它不起作用,因为c函数中的initm

这是我的第一个问题。到目前为止,我通过其他问题得到了很多答案,但现在没有更多的答案了

我工作的目的是使用一个用C编写的通信模块(get as.so)的开发堆栈。我想将它与python(cython)结合起来,因为所有其他软件都是这样编写的。在创建并测试了从cython到c的方向之后,我在最后几天为从c到cython的方向工作。堆栈对c函数中的函数进行了事件driffen调用,我想集成对cython函数的调用,用于日志记录和进一步的数据处理。但两天后我挂了电话。它不起作用,因为c函数中的initmodulename函数调用引发了一个错误。 所以我开发了下面的最小示例来让它在两个方向上工作,cython和c。这是一个扩展的例子

我有3个文件,main.c

#包括
#包括“caller.h”
int main(){
Py_初始化();
initcaller();
叫嘎嘎;
Py_Finalize();
返回0;
}
调用方.pyx的

来自quacker导入quack
cdef公共无效调用\u-quack():
庸医
def run():
“main.c”中的cdef外部:
int main()
main()
还有quacker.py

def-quack():
打印(“嘎嘎!”)
目标是导入调用方start run()作为函数,它调用c函数并回调call_-quack()

要编译,我使用(来自主项目):

使用setup.py

#setup.py文件
导入系统
导入操作系统
进口舒蒂尔
从distutils.core导入设置
从distutils.extension导入扩展
从Cython.Distutils导入生成\u ext
设置(
cmdclass={'build\u ext':build\u ext},
外部模块=[
分机(“呼叫者”,
sources=[“caller.pyx”,
],
include_dirs=[“/usr/include//python3.4”],
额外编译参数=[“-fopenmp”,“-O3”],
额外链接参数=[“-DSOME\u DEFINE\u OPT”,
“-L./some/extra/dependency/dir/”]
)
]
)    
编译和链接期间没有错误。 但是当我启动python3.4并导入调用者时,我得到以下错误

ImportError: /home/rvk/software/test/caller.cpython-34m.so: undefined symbol: initcaller
有人能帮我解决这个问题吗?我从来没有读过任何关于我们在两个方向上使用cython和c的例子!可能吗

我已经检查了cythonized c文件(caller.c)-有一个initcaller方法,但只适用于PY_MAJOR_版本<3

提前多谢

编辑

我通过删除main.c中的pyinitialize、initcaller和PyFinalize函数调用来实现它。也许这与问题有关,我已经在pyx中声明了main.c,所以它是编译库的一部分?!我不知道泄漏的原因是什么

新的main.c:

#包括
#包括“caller.h”
int main(){
叫嘎嘎;
返回0;
}

我还将其集成到主项目中。这里的挑战是,应该调用cython文件中的函数的c函数是一个回调c函数,因此有必要在cython文件中定义函数,在调用方.pyx中使用gil

def run():
    cdef extern from "main.c":
        int main()
    main()
它通过包含
main.c
而引起麻烦,而这反过来又包括
caller.h
,这是cython生成的代码所无法预料的。此外,调用
main.c
中定义的
main()。因此,“main.c”中的
cdefextern:
应该被删除

对于Python3.x,它类似于
PyInit\u modulename()
,而不是
initmodule()


0否决票接受是,我在cythonized文件中看到了这一点,但它不起作用-引发编译错误。你知道为什么吗?caller.c:915:16:错误:“PyInit_caller”PyMODINIT_FUNC PyInit_调用者的类型冲突(void)/*proto*//J.Werner最初,我没有注意到“main.c”
中的
cdef extern,只有
initcaller()/
PyInit\u modulename()
相关问题。我希望我的答案现在更有用。@J.J.Hakala如果我从“main.c”中删除$cdef extern,那么我得到的错误是,main.c未声明。我发现了一个双向工作的工作区,请参见问题的编辑。我不知道为什么它不像
def run():
    cdef extern from "main.c":
        int main()
    main()
int main() 
{
    Py_Initialize();
    PyInit_caller();
    call_quack();
    Py_Finalize();
    return 0;
}