在 C++ 中使用 Python 个对象

Using Python objects in C++

我正在编写一个代码,使用区间分析的方法计算非线性映射的图像,应用 minkowski 和并重复任意次数的迭代。

我已经在 Python 中编写了一个工作代码,但是我希望能够在 C++ 中实现算法中一些更 iteration/recursion 密集的部分,以便从提高的速度中获益.我过去使用 Cython 取得了很好的效果,但我想练习我的 C++。

此外,我的对象非常复杂,我宁愿避免用 C++ 实现它们(婴儿步骤!)。

所以我的问题是:

1) 在 C++ 中使用 Python 对象会阻碍效率的提高吗?

2) 如果不是,是否可以使用 Cython 包装一个 C++ 函数,该函数 iterates/recurses 覆盖 python 对象?

更具体地说,我有一个递归算法,它在 BST 的左右子节点上递归(虽然它是一个经过相当大修改的 BST,所以我不想陷入在实现它的细节中C++),但是运行时非常高,所以我想用C++来写。

是的。您将获得比纯 python 更高的速度,但与使用纯 C/C++ 时所获得的提升不相上下。如果你想处理 Python 对象,你需要通过 Python C/API;这增加了执行的开销,您必须为允许与 Python 交互而付出的代价。

请注意,这涉及很多复杂性,因为您需要熟悉 API 并阅读函数对对象引用的作用、如何创建列表、打包元组等。如果您只是创建几个 public Cython cdef 函数来包装对象上的方法,则可以跳过所有这些。这会生成为您处理这些问题的所有 CPython 代码。

一个包装和嵌入愚蠢对象的小例子可能看起来像这样(注意,我为此使用 .cc++ 有类似的步骤):

class PyClass(object):

    def __init__(self):
        self.data = []

    def add(self, val):
        self.data.append(val)

    def __str__(self):
        return "Data: " + str(self.data)

cdef public object createPyClass():
    return PyClass()

cdef public void addData(object p, int val):
    p.add(val)

cdef public char* printCls(object p):
    return bytes(str(p), encoding = 'utf-8')

使用 cython pycls.pyx 编译(对 c++ 使用 --cplus)将生成一个 .c.h 文件,分别包含源代码和函数声明。您现在需要做的就是创建一个启动 Python 的 main.c 文件,然后您就可以调用这些函数了:

#include "Python.h"   // Python.h always gets included first.
#include "pycls.h"    // Include your header file.

int main(int argc, char *argv[])
{
    Py_Initialize();   // initialize Python
    PyInit_pycls();    // initialize module (initpycls(); in Py2)
    PyObject *obj = createPyClass();
    for(int i=0; i<10; i++){
        addData(obj, i);
    }
    printf("%s\n", printCls(obj));
    Py_Finalize();
    return 0;
}

用适当的标志编译它(你可以从 python-config [Py2] 的 python3.5-config 获得):

gcc pycls.c main.c -L$(python3.5-config --cflags) -I$(python3.5-config --ldflags) -std=c99

将创建与您的对象交互的可执行文件:

./a.out
Data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

所有这些都是通过使用 Cython 以及生成 .h 头文件的 public 关键字来完成的。您也可以只用 Cython 编译一个 python 模块,然后自己创建 header/handle 额外的样板文件。因为我认为你不想被 C-API 学习所困扰,所以这不应该是正确的选择。

正如@freakish 在他的评论中指出的那样,提取数据 (numpy has a C-API you can use for this) 并以纯 C++ 的方式对其进行处理是理想的。一般来说,如果你在 C/C++ 中运行你的循环并在那里执行繁重的工作,你将获得很好的加速。