您的位置:首页 > 编程语言 > C语言/C++

C++ 调用 Python 初探(一)

2016-09-18 17:19 232 查看
为实现在C++中调用 Numpy接口下面对C++中调用Python进行讨论,

这里作为基础部分暂时不涉及对于Numpy的相应接口的调用,而仅仅是Python内置数据结构。

使用GCC配置 C++ 调用 Python 接口的方法

在CodeBlocks中编译器设置中设定, 外部链接库。

在搜索目录中定义:
编译:D:\Python27\include
链接器:D:\Python27\libs

链接器设置:
链接库:D:\Python27\libs\python27.lib

下面展开在C++ 中调用Python的相关讨论:

这里使用了支持C++ 11的GCC编辑器,找到Python相应的指针接口后,重写

相应的Python逻辑为C++,直接调用Python接口即可。(这可以大大加快程序的运行速率)。

一些用到的Python C++指针接口的说明:

void Py_Initialize
初始化python解释器,在调用其他API前应该完成相应的调用。

int PyRun_SimpleString(const char *command)

剩下的比较简单。

使用C++调用Python接口,一般会在调用函数及给出相应函数参数时用到char *format指针,

这个指针一般是用string对象进行初始化的,注意类型与提供的参数要一一对应,在编译

时会抛出warning, 并不能将char* 指向 string,这个现象可以忽视。

python的标准C接口是相对简单的,但Numpy的相应C接口相对复杂,故采用C++代码来重写算法

的方式来编程。

利用Py_INCREF及Py_DECREF可以对PyObject的指针进行引用增减操作,对已释放的内存进行

访问会出错,但这也是及时释放内存的方法。

在使用Python C API时的一个重要问题是内存的释放,如当为了得到python list的某一项时

有两个API接口,一种是PyList_GetItem 另一种是PySequence_GetItem,当使用前者是得到的

是对象(下标对应项)的引用,而后者是一个新的引用,即后者递增了引用计数,

故在使用后一个版本时要注意调用Py_DECREF进行引用计数递减,释放内存。

下面是一个简单的与上述内容相对应的C++代码:
#include<iostream>
using std::cout;
using std::endl;

#include<string>
using std::string;

#include<Python.h>

int set_all(PyObject *target, PyObject* item)
{

        int i, n;
        n = PyObject_Length(target);
        if (n < 0)
                return -1;
        for (i = 0;i < n; i++)
        {
                PyObject* index = PyInt_FromLong(i);
                if (!index)
                        return -1;
                if (PyObject_SetItem(target, index, item) < 0)
                {
                        Py_DECREF(index);
                        return -1;
                }

                Py_DECREF(index);
        }
        return 0;
}

long sum_list(PyObject* list)
{
        int i, n;
        long total = 0;
        PyObject * item;

        n = PyList_Size(list);
        if(n < 0)
                return -1;
        for(i = 0;i < n;i++)
        {
                item = PyList_GetItem(list, i);
                if (!PyInt_Check(item))continue;
                total += PyInt_AsLong(item);
        }

        return total;
}

long sum_sequence(PyObject* sequence)
{
        int i, n;
        long total = 0;
        PyObject *item;
        n = PySequence_Length(sequence);
        if(n < 0)
                return -1;
        for(i = 0;i < n;i ++)
        {
                item = PySequence_GetItem(sequence, i);
                if(item == NULL)
                        return -1;
                if(PyInt_Check(item))
                        total += PyInt_AsLong(item);
                Py_DECREF(item);
        }
        return total;
}

int main()
{
        PyObject *pModule, *pValue, *pModule0, *pValue0, *pList;
        Py_Initialize();
        pModule = PyImport_ImportModule("math");

        pValue=PyObject_CallMethod(pModule, "sqrt", "f", 100.0);
        cout << PyFloat_AsDouble(pValue) << endl;
        PyRun_SimpleString("print 'The work is done.'");

        pList = PyList_New(2);
        cout << PyList_GET_SIZE(pList) << endl;
        cout << "The type of ptr is or not list :" << PyList_Check(pList)<<endl;

        //Py_DECREF(pList);
        cout << "Another condition :"<< PyList_Check(pValue)<< endl;
        Py_INCREF(pList);
        Py_DECREF(pList);

        PyObject *t;
        t = PyTuple_New(3);
        PyTuple_SetItem(t, 0, PyInt_FromLong(1L));
        PyTuple_SetItem(t, 1, PyInt_FromLong(2L));
        PyTuple_SetItem(t, 2, PyString_FromString("three"));

        PyObject *tuple, *list;
        tuple = Py_BuildValue("(iis)", 1, 2, "three");
        list = Py_BuildValue("[iis]", 1, 2, "three");

        PyObject * pTuple;
        pTuple = Py_BuildValue("(iii)", 10,10, 10);
        PyObject* n = PyInt_FromLong(1000);
        int return_val;
        return_val = set_all(pTuple, n);
        cout << "The return val is :" << return_val <<endl;
        int num;
        num = PyObject_Length(pTuple);
        for(int i = 0;i < num; i++);
                cout << PyInt_AsLong(PyTuple_GetItem(pTuple, i)) << " ";
        cout << endl;

        PyObject * ppList;
        ppList = PyList_New(3);
        ppList = Py_BuildValue("[iii]", 1, 2, 3);
        num = PyObject_Length(ppList);

        cout << "Before pList is :\n";
        for(int i = 0;i < num; i++)
                cout << PyInt_AsLong(PyList_GetItem(ppList, i))<< " ";
        cout << endl;

        return_val = set_all(ppList, n);

        cout << "The return val :" <<return_val<< endl;
        cout << "Now the List is :";

        for(int i = 0;i < num; i ++)
                cout << PyInt_AsLong(PyList_GetItem(ppList, i)) << " ";
        cout << endl;

        cout << sum_list(ppList)<<endl;
        cout << sum_sequence(ppList) << endl;

        Py_Finalize();

        return 0;
}


上面提到的有关论述基本上是Python文档中与C进行交互的相关部分,这对于在C++中调用Python已经

足够,文档中剩余的基础部分基本上是对于各种API的列举介绍。(这里忽略了与异常相关的部分)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息