c语言与python通信_python和c++通信示例
先貼一個(gè)大牛寫的python與C++的通信的經(jīng)典文章:如何實(shí)現(xiàn) C/C++ 與 Python 的通信?
里面講到了不少方法來實(shí)現(xiàn)C++和python之間的通信,我看了之后深有感觸,但里面的例程序大多都是int或者string這樣容易轉(zhuǎn)換的,但如果是list呢,應(yīng)該如何傳遞到C++中。
于是在stackoverflow上轉(zhuǎn)了之后發(fā)現(xiàn)了這么一種方法,
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對(duì)象存儲(chǔ)在C對(duì)象指針中。這類似于“O”,但是接受兩個(gè)C參數(shù):第一個(gè)是Python類型對(duì)象的地址,第二個(gè)是對(duì)象指針存儲(chǔ)在其中的C變量(類型為PyObject *)的地址。如果Python對(duì)象沒有所需的類型,就會(huì)引發(fā)類型錯(cuò)誤(TypeError)。
Python的對(duì)象在底層的C語言中就是PyObject,通常用指針去表示也就是PyObject*.
看不懂沒關(guān)系,直接往下看。
list本身也是個(gè)對(duì)象,于是"O!"的格式就能將list對(duì)應(yīng)的那個(gè)對(duì)象的指針賦給pList.
但是我們得到list對(duì)象了,如何解析呢,畢竟里面有可能各種類型都有的。
我們必須了解list在C++中的函數(shù)庫:
此時(shí)(假設(shè)你用的是linux+python2.7),打開/usr/include/python2.7
你就會(huì)看到一堆頭文件。
大概就是這樣,然后你會(huì)發(fā)現(xiàn),里面有個(gè)叫l(wèi)istobject.h的東西,這個(gè)里頭就是對(duì)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 *);
風(fēng)格極度友好,純C打造,不像某模板庫源碼天花亂墜。
因?yàn)榭床坏骄唧w的實(shí)現(xiàn),我們只能從聲明里猜,還是很好猜的。
我們可以發(fā)現(xiàn):
PyAPI_FUNC(PyObject *) PyList_New(Py_ssize_t size);
這個(gè)肯定是創(chuàng)建的函數(shù)啦,顯而易見。返回值是一個(gè)PyObject*.
PyAPI_FUNC(PyObject *) PyList_GetItem(PyObject *, Py_ssize_t);
這個(gè)就是讀取指定項(xiàng)的函數(shù)了,英文名也顯而易見的。返回值也是PyObject*,畢竟list里面也都是對(duì)象,是對(duì)象就是PyObject。
PyAPI_FUNC(int) PyList_Append(PyObject *, PyObject *);
然后這個(gè)呢就是添加函數(shù)了,第一個(gè)參數(shù)是list指針,第二個(gè)是被你放入的新對(duì)象的指針。
然后是PyObject **ob_item,這個(gè)是定義在結(jié)構(gòu)體里頭的,熟悉C語言的就知道,指針的指針嘛,也就是list的頭,所以看到這里你就應(yīng)該知道,list里其實(shí)是裝指針的。因?yàn)槭荂寫的,所以也沒有private屬性,你想訪問就訪問。
其他函數(shù)就不解釋了,你應(yīng)該也看得懂。
接下來,如何用這幾個(gè)函數(shù)處理呢?
回到之前那段代碼里,有這么一句話:
PyArg_ParseTuple(args, "O!", &PyList_Type, &pList));
這個(gè)跑完之后,pList就是指向你的list的指針了。
然后我們要做的就是用PyList_GetItem把list中的每一個(gè)東西弄出來(簡(jiǎn)單起見,在python的代碼里就別往list里丟一些亂七八糟的東西了,不然像前面那樣得加一堆判斷異常什么的,我們現(xiàn)在只放整數(shù))
但這個(gè)整數(shù)傳到C++中可不是整數(shù),是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把每個(gè)我讀取出來的item做一個(gè)轉(zhuǎn)換,從python的整形轉(zhuǎn)為C++的整形,存入我們開辟的空間A中。
然后調(diào)用std::sort即可。
但是我們得到了排完序的數(shù)組怎么返回給python呢?
PyObject *new_list;
new_list=PyList_New(0);
for(i=0;i
{
PyList_Append(new_list,PyInt_FromLong(A[i]) );
}
很簡(jiǎn)單,也是用listobject.h中的函數(shù)。先用PyList_New來new一個(gè)list,然后往里頭加數(shù)據(jù)就可以了,不過你得加PyObject*才行,所以我們用
PyList_Append(new_list,PyInt_FromLong(A[i]) );
來做一個(gè)轉(zhuǎn)換。
最后我們把new_list返回去就可以了。具體的一些別的細(xì)節(jié)如導(dǎo)入導(dǎo)出,編譯請(qǐng)看文章首部的鏈接。
最后奉上完整代碼:
這個(gè)是C++部分,你得把這編譯成一個(gè)動(dòng)態(tài)鏈接庫(.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]
整個(gè)代碼寫下來其實(shí)沒什么用,畢竟你要sort在python里sort一下,也沒必要重復(fù)造輪子。
但是如果沒有人去做這種工作,那某些深度學(xué)習(xí)框架中調(diào)用GPU的操作也就做不出來了。
總結(jié)
以上是生活随笔為你收集整理的c语言与python通信_python和c++通信示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hadoop fs:du统计hdfs文件
- 下一篇: pycharm自带python环境_Py