在C ++中使用Python对象

时间:2016-06-01 19:56:09

标签: python c++ object cython

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

我已经用Python编写了一个工作代码,但我希望能够在C ++中实现一些更多的迭代/递归密集部分,以便从提高的速度中受益。我过去使用过Cython,效果很好,但我想练习C ++。

另外,我的对象很复杂,我宁愿避免在C ++中实现它们(宝贝步骤!)。

所以我的问题是:

1)在C ++中使用Python对象是否会阻止效率的提高?

2)如果没有,是否可以使用Cython包装迭代/递归python对象的C ++函数?

更具体地说,我有一个递归算法,可以对BST的左右子进行递归(尽管它是一个相当严格修改的BST,所以我不想陷入在C ++中实现它的细节)但是运行时非常禁止,所以我想用C ++编写它。

1 个答案:

答案 0 :(得分:1)

是。你将获得超过纯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进行编译(对--cplus使用c++)将分别生成包含源和函数声明的.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;
}

使用正确的标记(可以从python3.5-config [Py2]的python-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以及生成public头文件的.h关键字来完成的。您也可以使用Cython编译一个python模块,并自己创建标题/处理额外的样板。由于我认为你不想被C-API学习所困扰,所以这不应该是你想要的。

正如@freakish在评论中指出的那样,提取数据(numpy has a C-API you can use for this)并在纯C++中处理它是理想的。一般来说,如果你在C/C++中完成循环并在那里执行咕噜咕噜的工作,你将获得良好的加速。