C++和python混合程式設計之在python類建構函式中傳參方法
阿新 • • 發佈:2019-02-16
一、說明:C++專案中用到python相關的知識,這兩天研究了一下C++與python的混合程式設計,網上有很多這方面的介紹,但是怎麼使用python類的建構函式中傳參的介紹卻沒有,這裡研究一下,分享出來。(C++和python相互呼叫的相關介面查詢https://docs.python.org/2/index.html)
二、測試程式碼
1、C++程式碼:
/*=================CplusUsePython.h====================*/ #ifndef CPLUSUSEPYTHON_H #define CPLUSUSEPYTHON_H #include <Python.h> #include <string> using namespace std; class CplusUsePython { public: CplusUsePython(); ~CplusUsePython(); static CplusUsePython* instance() { static CplusUsePython instance; return &instance; } // 初始化相關操作 int init(const string pyFilePath, const string pyFileNameNoSuffix); // C++呼叫python函式 int CCallFunction(const string pyFuncName, const string message); // C++呼叫python類中的函式 int CCallClassFunc(const string pyFuncName, const string name, const int age); private: PyObject *pName; PyObject *pModule; PyObject *pFunc; PyObject *pArgs; PyObject *pClass; PyObject *pInstance; }; #endif // CPLUSUSEPYTHON_H /*=================CplusUsePython.cp====================*/ #include "CplusUsePython.h" #include <sstream> CplusUsePython::CplusUsePython() { } CplusUsePython::~CplusUsePython() { if (Py_IsInitialized()) { if (pName) Py_DECREF(pName); if (pArgs) Py_DECREF(pArgs); if (pModule) Py_DECREF(pModule); if (pFunc) Py_DECREF(pFunc); if (pClass) Py_DECREF(pClass); if (pInstance) Py_DECREF(pInstance); Py_Finalize(); } } //************************************ // 函式名稱: init // 函式說明:初始化相關操作 // 返 回 值: int // 參 數: const string pyFilePath // 參 數: const string pyFileNameNoSuffix // 作 者:ISmileLi // 作成日期:2018/11/25 // 修改記錄: //************************************ int CplusUsePython::init(const string pyFilePath, const string pyFileNameNoSuffix) { int ret = 0; if (pyFilePath.empty() || pyFileNameNoSuffix.empty()) return -1; Py_Initialize(); pName = NULL; pModule = NULL; pFunc = NULL; pArgs = NULL; pClass = NULL; pInstance = NULL; // 判斷初始化是否成功 if (!Py_IsInitialized()) return -2; // 呼叫python中需要使用的模組 ret = PyRun_SimpleString("import sys"); if (ret != 0) { // 匯入失敗,關閉python呼叫 Py_Finalize(); return -3; } // 匯入python檔案的相關操作 if (ret == 0) { stringstream strpycmd; strpycmd << "sys.path.append('" << pyFilePath << "')"; ret = PyRun_SimpleString(strpycmd.str().c_str()); } if (ret != 0) { Py_Finalize(); return -4; } pName = PyString_FromString(pyFileNameNoSuffix.c_str()); if ((pModule = PyImport_Import(pName)) == NULL || pName == NULL) { Py_Finalize(); return -5; } return 0; } //************************************ // 函式名稱: CCallFunction // 函式說明:C++呼叫python中的函式 // 返 回 值: int // 參 數: const string pyFuncName // 參 數: const string message // 作 者:ISmileLi // 作成日期:2018/11/25 // 修改記錄: //************************************ int CplusUsePython::CCallFunction(const string pyFuncName,const string message) { if (pyFuncName.empty() || message.empty()) { return -1; } pFunc = PyObject_GetAttrString(pModule, pyFuncName.c_str()); if(!pFunc) { return -2; } // 呼叫python函式,s表示傳入引數是字串型別 PyObject *pRet = PyObject_CallFunction(pFunc, "s", (char*)message.c_str()); if(pRet) { Py_DECREF(pRet); } else { return -3; } return 0; } //************************************ // 函式名稱: CCallClassFunc // 函式說明:C++呼叫python類中的函式 // 返 回 值: int // 參 數: const string pyFuncName // 參 數: const string name // 參 數: const string age // 作 者:ISmileLi // 作成日期:2018/11/25 // 修改記錄: //************************************ int CplusUsePython::CCallClassFunc(const string pyFuncName,const string name, const int age) { if (pyFuncName.empty() || name.empty() || age <= 0) { return -1; } // 向Python傳引數是以元組(tuple)的方式傳遞的 pArgs = PyTuple_New(2); // PyObject* Py_BuildValue(char *format, ...) 將C++的變數轉換成一個Python物件 // s 表示字串,i 表示整型變數,f 表示浮點數 PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", name.c_str())); PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", age)); // 增加支援呼叫類中方法的操作 pClass = PyObject_GetAttrString(pModule,"ISmileLi"); // DrawPic為類的名字 if(!pClass) { return -2; } // 傳入python建構函式中的兩個引數 pInstance = PyInstance_New(pClass,pArgs,NULL); if(!pInstance) { return -3; } // 呼叫類中的函式 pFunc = PyObject_CallMethod(pInstance,(char*)pyFuncName.c_str(),NULL,NULL); if(!pFunc) { return -4; } return 0; } /*=================main.c================*/ #include <Python.h> #include <iostream> #include <string> #include "CplusUsePython.h" using namespace std; int main () { // C++和python相互呼叫的相關介面查詢https://docs.python.org/2/index.html string pyFilePath = "/work/test/testC++/test_C_use_Python"; int ret = CplusUsePython::instance()->init(pyFilePath,"ISmileLi"); if(ret != 0) { cout << "init failure!" << endl; } ret = CplusUsePython::instance()->CCallFunction("print_message","this is test C++ use python!"); ret = CplusUsePython::instance()->CCallClassFunc("print_name","LiSa",18); ret = CplusUsePython::instance()->CCallClassFunc("print_age","LiSa",18); ret = CplusUsePython::instance()->CCallClassFunc("print_name_age","LiSa",18); return 0; }
2、python程式碼
#filename: ISmileLi.py # -*- coding: utf-8 -*- class ISmileLi: def __init__(self,name,age): self.name = name self.age = age def print_name(self): print("===in function print_name===") print("name:",self.name) def print_age(self): print("===in function print_age===") print("age:",self.age) def print_name_age(self): print("===in function print_name_age===") print("name:%s age:%d" % (self.name,self.age)) def print_message(message): print("===in function print_message===") print("message:",message)
三、執行結果
說明:由於我也不擅長python,如有錯誤歡迎指正。