c语言与python通信_python和c++通信示例

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

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

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

PyObject *pList;

PyObject *pItem;

Py_ssize_t n;

int i;

if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &pList)) {

PyErr_SetString(PyExc_TypeError, "parameter must be a list.");

return NULL;

}

n = PyList_Size(pList);

for (i=0; i

pItem = PyList_GetItem(pList, i);

if(!PyInt_Check(pItem)) {

PyErr_SetString(PyExc_TypeError, "list items must be integers.");

return NULL;

}

}

"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

你就会看到一堆头文件。

大概就是这样,然后你会发现,里面有个叫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

{

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

{

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#include #includevoid quick_sort(int *a,int length) {

std::sort(a,a+length);

}

static PyObject * _quick_sort(PyObject *self, PyObject *args)

{

PyObject *pList;

PyObject *new_list;

PyObject *pItem;

Py_ssize_t n;

int i;

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

n = PyList_Size(pList);

new_list=PyList_New(0);

n=(int)n;

int *A=new int[n];

for (i=0; i

{

pItem = PyList_GetItem(pList, i);

A[i]=PyInt_AsLong(pItem);

}

quick_sort(A,n) ;

for(i=0;i

{

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

}

delete A;

return new_list;

}

static PyMethodDef SortMethods[] = {

{

"quick_sort",

_quick_sort,

METH_VARARGS,

""

},

{NULL, NULL, 0, NULL}

};

PyMODINIT_FUNC initsort(void) {

(void) Py_InitModule("sort", SortMethods);

}

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

然后是python部分

#文件名:aa.py

from sort import quick_sort

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

b=quick_sort(a)

print(b)

命令是:python2 aa.py

最后就能看到输出啦:

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值