网站设计模板图片,南宁网站推广手段,网站备案的影布怎么做,淮安神舟建设招标网站先贴一个大牛写的python与C的通信的经典文章#xff1a;如何实现 C/C 与 Python 的通信#xff1f;
里面讲到了不少方法来实现C和python之间的通信#xff0c;我看了之后深有感触#xff0c;但里面的例程序大多都是int或者string这样容易转换的#xff0c;但如果是list呢的通信的经典文章如何实现 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 (i0; 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中的函数库
此时(假设你用的是linuxpython2.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,alength);
}
/*
略去大段代码
*/
int *Anew int[n];
for (i0; 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_listPyList_New(0);
for(i0;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,alength);
}
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_listPyList_New(0);
n(int)n;
int *Anew int[n];
for (i0; i
{
pItem PyList_GetItem(pList, i);
A[i]PyInt_AsLong(pItem);
}
quick_sort(A,n) ;
for(i0;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]
bquick_sort(a)
print(b)
命令是:python2 aa.py
最后就能看到输出啦
[0, 1, 2, 3, 4, 5, 6, 7]
整个代码写下来其实没什么用毕竟你要sort在python里sort一下也没必要重复造轮子。
但是如果没有人去做这种工作那某些深度学习框架中调用GPU的操作也就做不出来了。