我正在一个项目中,我需要在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 ++程序中调用这些函数?预先谢谢你。
答案 0 :(得分:3)
我不确定为什么它会为公共函数生成错误的名称-它与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
文件名)
答案 1 :(得分:-2)
正常的cython开发模式则相反-您将使用它来从python调用C ++代码。
关于cython常用用法的简单描述是“用类似python的高级语言编写代码,并将其转换为python扩展的C源代码”
生成的C代码不可读,也不能用于C。
tl; dr使用cython使您的C / C ++程序可从python调用,并编写python代码来调用它。