python n个list如何组成矩阵_python和c++通信示例

先贴一个大牛写的python与C++的通信的经典文章:如何实现 C/C++ 与 Python 的通信?

里面讲到了不少方法来实现C++和python之间的通信,我看了之后深有感触,但里面的例程序大多都是int或者string这样容易转换的,但如果是list呢,应该如何传递到C++中。

于是在stackoverflow上转了之后发现了这么一种方法,

PyObject 

"O!" (object)[typeobject, PyObject *]
将Python对象存储在C对象指针中。这类似于“O”,但是接受两个C参数:第一个是Python类型对象的地址,第二个是对象指针存储在其中的C变量(类型为PyObject *)的地址。如果Python对象没有所需的类型,就会引发类型错误(TypeError)。
Python的对象在底层的C语言中就是PyObject,通常用指针去表示也就是PyObject*.

看不懂没关系,直接往下看。

list本身也是个对象,于是"O!"的格式就能将list对应的那个对象的指针赋给pList.

但是我们得到list对象了,如何解析呢,毕竟里面有可能各种类型都有的。

我们必须了解list在C++中的函数库:

此时(假设你用的是linux+python2.7),打开/usr/include/python2.7

你就会看到一堆头文件。

65646290ccf4ccdf7134c67ce835a324.png

大概就是这样,然后你会发现,里面有个叫listobject.h的东西,这个里头就是对list的一些声明。

#ifndef Py_LISTOBJECT_H
#define Py_LISTOBJECT_H
#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size
     *     ob_item == NULL implies ob_size == allocated == 0
     * list.sort() temporarily sets allocated to -1 to detect mutations.
     *
     * Items must normally not be NULL, except during construction when
     * the list is not yet visible outside the function that builds it.
     */
    Py_ssize_t allocated;
} PyListObject;

PyAPI_DATA(PyTypeObject) PyList_Type;

#define PyList_Check(op) 
    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS)
#define PyList_CheckExact(op) (Py_TYPE(op) == &PyList_Type)
PyAPI_FUNC(PyObject *) PyList_New(Py_ssize_t size);
PyAPI_FUNC(Py_ssize_t) PyList_Size(PyObject *);
PyAPI_FUNC(PyObject *) PyList_GetItem(PyObject *, Py_ssize_t);
PyAPI_FUNC(int) PyList_SetItem(PyObject *, Py_ssize_t, PyObject *);
PyAPI_FUNC(int) PyList_Insert(PyObject *, Py_ssize_t, PyObject *);
PyAPI_FUNC(int) PyList_Append(PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) PyList_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t);
PyAPI_FUNC(int) PyList_SetSlice(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *);
PyAPI_FUNC(int) PyList_Sort(PyObject *);
PyAPI_FUNC(int) PyList_Reverse(PyObject *);
PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *);
PyAPI_FUNC(PyObject *) _PyList_Extend(PyListObject *, PyObject *);

风格极度友好,纯C打造,不像某模板库源码天花乱坠。

因为看不到具体的实现,我们只能从声明里猜,还是很好猜的。

我们可以发现:

PyAPI_FUNC(PyObject *) PyList_New(Py_ssize_t size);

这个肯定是创建的函数啦,显而易见。返回值是一个PyObject*.

PyAPI_FUNC(PyObject *) PyList_GetItem(PyObject *, Py_ssize_t);

这个就是读取指定项的函数了,英文名也显而易见的。返回值也是PyObject*,毕竟list里面也都是对象,是对象就是PyObject。

PyAPI_FUNC(int) PyList_Append(PyObject *, PyObject *);

然后这个呢就是添加函数了,第一个参数是list指针,第二个是被你放入的新对象的指针。

然后是PyObject **ob_item,这个是定义在结构体里头的,熟悉C语言的就知道,指针的指针嘛,也就是list的头,所以看到这里你就应该知道,list里其实是装指针的。因为是C写的,所以也没有private属性,你想访问就访问。

其他函数就不解释了,你应该也看得懂。

接下来,如何用这几个函数处理呢?

回到之前那段代码里,有这么一句话:

PyArg_ParseTuple(args, "O!", &PyList_Type, &pList));

这个跑完之后,pList就是指向你的list的指针了。

然后我们要做的就是用PyList_GetItem把list中的每一个东西弄出来(简单起见,在python的代码里就别往list里丢一些乱七八糟的东西了,不然像前面那样得加一堆判断异常什么的,我们现在只放整数)

但这个整数传到C++中可不是整数,是PyObject,

void quick_sort(int *a,int length) {
    std::sort(a,a+length);
}
/*
略去大段代码
*/
int *A=new int[n];
    for (i=0; i<n; i++) 
    {
        pItem = PyList_GetItem(pList, i);
        A[i]=PyInt_AsLong(pItem);
    }
quick_sort(A,n) ;

于是,我们得用PyInt_AsLong把每个我读取出来的item做一个转换,从python的整形转为C++的整形,存入我们开辟的空间A中。

然后调用std::sort即可。

但是我们得到了排完序的数组怎么返回给python呢?

PyObject *new_list;
new_list=PyList_New(0);
for(i=0;i<n;i++)
    {
        PyList_Append(new_list,PyInt_FromLong(A[i]) );
    }

很简单,也是用listobject.h中的函数。先用PyList_New来new一个list,然后往里头加数据就可以了,不过你得加PyObject*才行,所以我们用

PyList_Append(new_list,PyInt_FromLong(A[i]) );

来做一个转换。

最后我们把new_list返回去就可以了。具体的一些别的细节如导入导出,编译请看文章首部的链接。

最后奉上完整代码:

这个是C++部分,你得把这编译成一个动态链接库(.so文件)

//文件名:sort.cpp

命令是:g++ -fPIC -shared sort.cpp -o sort.so -I/usr/include/python2.7/ -lpython2.7

然后是python部分

#文件名:aa.py

命令是:python2 aa.py

最后就能看到输出啦:

[0, 1, 2, 3, 4, 5, 6, 7]

整个代码写下来其实没什么用,毕竟你要sort在python里sort一下,也没必要重复造轮子。

但是如果没有人去做这种工作,那某些深度学习框架中调用GPU的操作也就做不出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值