【问题标题】:Call C code with cython and cython-code from c使用 cython 和来自 c 的 cython-code 调用 C 代码
【发布时间】:2016-07-20 09:39:05
【问题描述】:

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

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

我有 3 个文件,ma​​in.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-function并回调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-method,但仅适用于 PY_MAJOR_VERSION

提前非常感谢

编辑

我通过删除 ma​​in.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 函数是回调 c 函数,因此有必要在 cython 文件中定义函数 with gil

【问题讨论】:

    标签: python cython


    【解决方案1】:

    caller.pyx

    def run():
        cdef extern from "main.c":
            int main()
        main()
    

    包含main.c 会引起麻烦,而caller.h 又包含caller.h,这是cython 生成的代码所未预料到的。此外,在 python 解释器中调用 main.c 中定义的 main() 可能会导致麻烦。所以cdef extern from "main.c":应该被删除。

    在 python 3.x 的情况下,它类似于PyInit_modulename(),而不是initmodule()

    int main() 
    {
        Py_Initialize();
        PyInit_caller();
        call_quack();
        Py_Finalize();
        return 0;
    }
    

    【讨论】:

    • 0 否决票接受 是的,我在 cythonized 文件中看到了这一点,但它不起作用 - 引发了编译错误。你知道为什么吗? caller.c:915:16:错误:'PyInit_caller' PyMODINIT_FUNC PyInit_caller(void) 的类型冲突; /*原型*/
    • @J.Werner 我最初没有注意到cdef extern from "main.c",只有initcaller(); / PyInit_modulename() 相关问题。我希望我的回答现在更有用。
    • @J.J. Hakala 如果我从“main.c”中删除 $cdef extern,那么我得到的错误是 main.c 未声明。我找到了一个可以双向工作的解决方法,请参阅问题的编辑。我不知道为什么它不像cython user guide
    猜你喜欢
    • 2011-07-16
    • 2012-07-26
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2020-09-13
    • 2021-10-30
    相关资源
    最近更新 更多