C++如何調(diào)用python并取返回值
C++調(diào)用python并取返回值
前面介紹了用python調(diào)用C++時(shí)用swig工具,現(xiàn)在簡(jiǎn)單介紹一下C++調(diào)用python并取返回值的過(guò)程
python文件test.py
class tester: def add(self, a, b): return a + b
新建一個(gè)VS控制臺(tái)項(xiàng)目
main.cpp所有的源碼如下:
#include <stdio.h> #include <python.h> #include <windows.h> void main() { Py_Initialize(); // 初始化python虛擬機(jī) PyObject* pyMod = PyImport_ImportModule("test"); // 加載test.py文件 PyObject* pyDict = PyModule_GetDict(pyMod); // 獲取test模塊中的字典 PyObject* pyCls = PyDict_GetItemString(pyDict, "tester"); // 從字典中查找tester類 PyObject* PyIns = PyInstance_New(pyCls, NULL, NULL); // 創(chuàng)建tester類 PyObject* pyRet = PyObject_CallMethod(pyIns, "add", "ii", 5, 6); // 調(diào)用tester.add方法,傳入2個(gè)int型參數(shù) int ok = -1; int retok = PyArg_Parse(pyRet, "i", &ok); // 從返回值從取出int型返回值 Py_Finalize(); system("pause"); }
整個(gè)過(guò)程最重要的是 PyBoject_CallMethod,傳入的參數(shù)類型一定不能搞錯(cuò)。
還有取返回值的時(shí)候PyArg_Parse取單個(gè)返回值,要是取多個(gè)的可以用PyArg_ParseTuple,要取的類型也必須完全匹配。
c++調(diào)用python時(shí)參數(shù)傳遞和返回值解析
通過(guò)python接口在cpp中調(diào)用python函數(shù)時(shí),構(gòu)建傳參和解析返回值都會(huì)用到python內(nèi)的變量類型和c++的變量類型之間的轉(zhuǎn)換。
返回值是numpy等復(fù)雜結(jié)構(gòu)的數(shù)據(jù)時(shí),可以通過(guò)先轉(zhuǎn)換為list等類型再返回,或者單獨(dú)構(gòu)建一個(gè)函數(shù),獲取numpy內(nèi)某個(gè)位置的變量的函數(shù)。
下面幾個(gè)基礎(chǔ)類型的返回值解析
#python #返回一個(gè)參數(shù) def returnInt(a,b): return a+b #返回兩個(gè)相同類型的參數(shù) def returnTwoInt(): return 1,2 #返回字符串 def returnString(): srt = 'hello world' return srt #返回list def returnList(): para = [1, 2, 3, 4] return 1,para.tolist() #返回兩個(gè)不同類型的參數(shù) def returnTwo(): para = [1, 2, 3, 4] return 1,para.tolist() #返回矩陣 def returnMat(): img = cv2.imread('test1.bmp',cv2.IMREAD_GRAYSCALE) return img
//調(diào)用python函數(shù),返回的數(shù)據(jù)統(tǒng)一為PyObject類型,需要根據(jù)實(shí)際類型進(jìn)行解析 PyObject* pReturn = PyObject_CallObject(pFunc, pArgs); //當(dāng)不需要傳參時(shí),可以將參數(shù)位置為空 PyObject* pReturn = PyObject_CallObject(pFunc,NULL);
PyObject為結(jié)構(gòu)體,參數(shù)ob_type->tp_name 為數(shù)據(jù)的類型
//不同類型參數(shù)傳遞 PyObject* p = PyTuple_New(4); for (int i = 0; i < 4; i++) PyTuple_SetItem(p, i, Py_BuildValue("i", i)); PyObject* pArgs = PyTuple_New(2); PyTuple_SetItem(pArgs, 0,Py_BuildValue ("i",1)); PyTuple_SetItem(pArgs, 0,Py_BuildValue ("O",p)); //返回為list double temp; int i_size = PyList_Size(pReturn); for (int i = 0; i < i_size; ++i) { PyArg_Parse(PyList_GetItem(pReturn, i), "d", &temp); std::cout << "return result is " << (temp) << std::endl; } //返回為 int 和 list 兩個(gè)不同類型的參數(shù) PyArg_Parse(PyTuple_GetItem(pReturn, 0), "d", &temp); std::cout << "temp is " << (temp) << std::endl; PyObject* pReturnlist; PyArg_Parse(PyTuple_GetItem(pReturn, 1), "O", &pReturnlist); i_size = PyList_Size(pReturnli); for (int i = 0; i < i_size; ++i) { PyArg_Parse(PyList_GetItem(pReturnli, i), "d", &temp); std::cout << "return result is " << (temp) << std::endl; } //返回單獨(dú)一個(gè)變量 //構(gòu)建輸入 PyObject* pArgs = PyTuple_New(2); PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 1)); PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 1)); PyObject* pReturn2 = PyObject_CallObject(pFunc, pArgs); //解析 int nResult1; //解析為int PyArg_Parse(pReturn2, "i", &nResult1); std::cout << "add=" << nResult1 << std::endl; double nResultd; //解析為double PyArg_Parse(pReturn2, "d", &nResultd); std::cout << "add=" << nResultd << std::endl; //返回字符串 //解析方法1: PyObject* repr = PyObject_Repr(pReturn); PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "strict"); char* result = PyBytes_AsString(str); std::cout << result << std::endl; //解析方法2: char* pstr = NULL; PyArg_Parse(pReturn, "s", &pstr); std::cout << pstr << std::endl; //返回多個(gè)變量 //循環(huán)解析 int nResult; i_size = PyTuple_Size(pReturn); for (int i = 0; i < i_size; ++i) { PyArg_Parse(PyTuple_GetItem(pReturn, i), "i", &nResult); std::cout << "return result is " << (nResult) << std::endl; } //直接解析 int nResult1; int nResult2; PyArg_ParseTuple(pReturn,"i|i", &nResult1, &nResult2); std::cout << "return " << nResult5<< ' ' << nResult6 << std::endl; //解析二維矩陣 //獲得序列長(zhǎng)度,即行數(shù) Py_ssize_t rsize = PyObject_Size(pReturn); std::cout << rsize << std::endl; //轉(zhuǎn)換到迭代器,用于提取數(shù)據(jù) PyObject* iter = PyObject_GetIter(pReturn5); while (true) { //獲取矩陣的第一行 PyObject* next = PyIter_Next(iter); if (!next) { // nothing left in the iterator break; } if (!PyList_Check(next)) { // error, we were expecting a list value } //獲得當(dāng)前行的數(shù)據(jù)數(shù)量 Py_ssize_t foosize = PyObject_Size(next); std::cout << foosize << std::endl; //轉(zhuǎn)換到迭代器,用于獲取數(shù)據(jù) PyObject* iter2 = PyObject_GetIter(next); while (true) { PyObject* next2 = PyIter_Next(iter2); if (!next2) break; if (!PyFloat_Check(next2)) {// error, we were expecting a floating point value} double foo = PyFloat_AsDouble(next2); std::cout << foo << " "; } std::cout << std::endl; }
python手冊(cè),接口的使用示例等
//解析常用字段: // b <=>char 0-255的那個(gè)char // c <=>char 單個(gè)字符 // h <=>short int // l <=>long int // f <=>float // d <=>double // s <=>char* // O <=> PyObject
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言非遞歸算法解決快速排序與歸并排序產(chǎn)生的棧溢出
上期我們講完了排序算法下,不知道小伙伴們有沒(méi)有發(fā)現(xiàn)一個(gè)問(wèn)題,快速排序和歸并排序我們都是用遞歸來(lái)實(shí)現(xiàn)的,可能有小伙伴會(huì)問(wèn),如果說(shuō)數(shù)據(jù)量很多話,棧區(qū)空間會(huì)不會(huì)不夠用呢?這期我們就來(lái)解決使用遞歸實(shí)現(xiàn)的排序?qū)е聴R绯鋈绾谓鉀Q2022-04-04C語(yǔ)言實(shí)現(xiàn)推箱子游戲的地圖編輯器
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)推箱子游戲的地圖編輯器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02C++友元(Friend)用法實(shí)例簡(jiǎn)介
這篇文章主要介紹了C++友元(Friend)用法,對(duì)于C++的學(xué)習(xí)來(lái)說(shuō)有很好的參考價(jià)值,需要的朋友可以參考下2014-08-08C++日期類(Date)實(shí)現(xiàn)的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C++語(yǔ)言實(shí)現(xiàn)日期類(Date),可以實(shí)現(xiàn)確定某年某月有多少天、打印日期等功能,感興趣的可以了解一下2022-07-07