在 C++ 程序中调用 Cython (Python3.6)
Posted
技术标签:
【中文标题】在 C++ 程序中调用 Cython (Python3.6)【英文标题】:Call Cython (Python3.6) in C++ Program 【发布时间】:2018-07-12 17:36:39 【问题描述】:我正在做一个项目,我需要在 C++ 中嵌入一些 python 代码。我一直在尝试 Cython 一段时间,但我仍然有很多问题。这是我尝试过的演示。
这里有几个包含结构和函数的文件:
首先,这是文件cat.pyx
cdef public struct Cat:
int num
cdef public setCatNum(Cat* cat):
cat.num = 100
cdef public int getCatNum(Cat* cat):
return cat.num
及其.pxd
文件cat.pxd
:
cdef public struct Cat:
int num
cdef public setCatNum(Cat* )
cdef public int getCatNum(Cat* )
这是我的setup.py
:
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [
Extension("cat", ["cat.pyx"], include_dirs=['.']),
]
setup(
name='dotest',
cmdclass='build_ext': build_ext,
ext_modules=ext_modules,
script_args=['build_ext'],
options='build_ext':'inplace':True, 'force':True
)
它可以正确编译,但是在生成的cat.h
文件中,函数声明是别的东西:
__PYX_EXTERN_C PyObject *__pyx_f_3cat_setCatNum(struct Cat *);
__PYX_EXTERN_C int __pyx_f_3cat_getCatNum(struct Cat *);
那么我如何在我的 C/C++ 程序中调用这些函数呢?提前谢谢你。
【问题讨论】:
你读过this documentation?我假设你有,因为你正确地制作了函数public
。我认为它应该生成更简单的名称...
是的,我确实阅读了那个例子。它说在 python 3.x 中我应该导入一个模块。但是我不太明白如何使用该模块来调用文档中的那些函数。
【参考方案1】:
我不确定为什么它会为公共函数生成混乱的名称 - 它与 the documentation 背道而驰。然而,它也为我做。我怀疑这是一个错误,但目前建议您只使用损坏的名称。
您可能希望将setCatNum
的返回类型设置为void
。目前它返回一个没有用的PyObject*
(总是None
),这意味着你必须处理它的引用计数。
cdef public void setCatNum(Cat* )
我认为您感到困惑的是 Python 2 和 3 之间的区别。文档建议将 init<modulename>
替换为
err = PyImport_AppendInittab("modulename", PyInit_modulename);
Py_Initialize();
modulename_module = PyImport_ImportModule("modulename");
这是您需要进行的唯一更改 - 您实际上不需要使用模块对象。
一个工作示例:
#include <Python.h>
#include "cat.h"
#include <iostream>
int main()
auto err = PyImport_AppendInittab("cat", PyInit_cat);
if (err)
std::cout << "ERROR!\n";
return 1;
Py_Initialize();
auto cat_module = PyImport_ImportModule("cat"); // you don't actually have to do anything with this module object
Cat c;
__pyx_f_3cat_setCatNum(&c);
std::cout << __pyx_f_3cat_getCatNum(&c) << "\n";
Py_Finalize();
使用
在 Linux 上成功编译g++ example_cpp.cpp -o example `python3-config --includes --libs` ./cat.cpython-36m-x86_64-linux-gnu.so
(您可能需要更改确切的 cat
文件名)
【讨论】:
非常感谢。它现在也为我工作。但是有没有其他方法可以避免这些名称损坏? @hiimdaosui 这很奇怪,但是当我使用“cython cat.pyx”构建时,我得到的函数名称不会被修改... @ead 当我尝试cython cat.pyx
时,它仍然给了我错位的功能......
我认为这可能是某些 Cython 版本中引入的错误。我会确保 Cython 更新到最新版本,如果不能解决它,请在 github 上提交错误报告
我会尝试删除(或修复?)cat.pxd
【参考方案2】:
正常的 cython 开发模式完全相反——你可以使用它从 python 调用 C++ 代码,而不是。
对 cython 常见用法的简单描述是“用类似 python 的高级语言编写代码,然后将其转换为用于 python 扩展的 C 源代码”
生成的 C 代码不可读,不打算从 C 中使用。
tl;dr 使用 cython 使您的 C/C++ 程序可从 python 调用,并编写 python 代码来调用它。
【讨论】:
到目前为止,这不是我从其他资源中发现的。喜欢***.com/questions/22589868/…。但我认为这只是我的代码不起作用,可能有解决方案。 @hiimdaosui 我从来没有说过不可能,只是不正常——就像逆潮流而行 @hiimdaosui 这是一本不错的读物twistedmatrix.com/users/glyph/rant/extendit.html 好的,我明白你在说什么。但是在我的项目中,我已经有很多用 python 编码的功能,它们严重依赖于一些第三方库,如 opencv 和 tensorflow。但最终我需要使用 C++ 程序来调用这些函数。所以我在这里很困惑。我必须用 C++ 重写所有这些代码吗? @hiimdaosui “但是我需要使用 C++ 程序来调用这些函数” 为什么?那很可能是假的!是什么迫使您从 C++ 调用它们?难道你不能只使用 python 并从 python 调用 C++ 部分吗?以上是关于在 C++ 程序中调用 Cython (Python3.6)的主要内容,如果未能解决你的问题,请参考以下文章