日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++调用Python函数

發布時間:2023/12/9 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++调用Python函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

From: http://www.flatws.cn/article/program/c/2010-08-24/9677.html

?? ? Python代碼在實現某些功能的時候非常方便,如果能夠將Python代碼與C++程序結合起來,那么一定會使Problem Solving方便許多(比如,游戲腳本系統)~

?? ?從學完Python開始就一直想研究一下C++內嵌Python是怎么回事,可是每次都堅持不下來。。。今天上校內,偶然間看到同學求助,怎么實現輸入表達式輸出結果~我想到了Python的builtin函數eval,正好借這個機會研究一下怎么實現C++調用Python函數!

?? ?假定您的系統中已經安裝了Python,我使用的版本是2.6~

?? ?1.配置IDE。

?? ?我用的是VS2008,只需要將Python安裝路徑下的include文件夾和libs文件夾添加到C++目錄中即可。步驟是:Tools -> Options -> Project & Solution -> VC++ Dir選擇右上的Dropdown List,分別將include文件夾和libs文件夾添加到include和lib項中。

?? ?2.編寫Python腳本。

?? ?為了完成自動計算值的功能,我寫了如下的腳本(文件名是python_code.py):

def calculate(expression):try: result = eval(expression) except:print 'Eval error!'return Nonereturn result
??? 將這個文件與C++程序文件放到同一目錄下,這樣保證編譯器可以根據相對路徑找到。

?? ?3.Python嵌入的方式 - 高級vs低級

?? ?接下來進入C++內嵌Python函數的關鍵部分了。根據官方的幫助文檔,有兩個類型的Python調用,High Level與Low Level。High Level就是調用者不需要管理與Python相關的內存,只有3行代碼即可,分別是Py_Initialize()來初始化解釋器(注意,此時程序仍然是由C++的編譯器進行編譯),調用PyRun_SimpleString()其中參數是要執行的Python代碼,如果是一個確定的Python文件,那么我們可以調用PyRun_SimpleFile()直接執行Python文件。最后調用Py_Finalize()方法結束解釋器工作。

?? ?使用High Level對程序員的要求非常少,基本就是會寫Python代碼就會在C++中調用Python的方法,但是弊端就是當前程序不能與Python的方法進行數據的交互,所以局限性非常大。

?? ?所以,如果我們需要與Python程序進行交互,比如計算表達式的值,我們只能使用低級的方法了。

?? ?4.Low Level程序編寫步驟。

?? ?說實話,以前幾次當我想學習Python內嵌的時候都是因為看到為了進行Low Level調用而編寫的冗長的C++代碼,實在是太恐怖了。。可是今天靜下來看一看其實只有4步:

?? ?(1)導入要用到的模塊:

?? ? 要導入模塊其實很簡單,首先我們需要提供模塊的文件名,注意,跟Python中導入模塊一樣,這里的文件名不能包含".py"后綴,比如我的文件名是python_code.py,我在程序中只需要提供"python_code"這個字符串就可以了。這一部分代碼如下(注意使用到的兩個函數:PyString_FromString和PyImport_Import):

PyObject *pyFileName = PyString_FromString(filename.c_str()); PyObject *pyMod = PyImport_Import(pyFileName); // load the module
??? 注意,在C++中一切Python的object都是用PyObject*來代替。第一行語句將C++中的char數組轉化為Python中的字符串,然后利用這個文件名導入模塊!請注意函數是PyImport_Import,而不是別的。

?? ?好了,模塊導入之后我們需要驗證模塊導入是否成功,如果成功我們就可以進行第二步了,找到我們要調用的方法。

?? ?(2)找到要調用的方法。

?? ?基本原理是這樣的,在C++中,如果我們有了模塊,就可以獲得模塊對應的attr列表(dir(模塊名)),然后我們就可以利用我們所需要的方法名找到我們所需要的那個attr。找到之后我們要判斷時候找到成功,而且是否是可以調用的(callable)。這部分代碼如下:

// load the function PyObject *pyFunc = PyObject_GetAttrString(pyMod, methodname.c_str()); if(pyFunc && PyCallable_Check(pyFunc)) {// talk later!!! }
??? 第一句話首先利用PyObject_GetAttrString找到我們所需的“方法”對象,然后檢測對象時候有效,是否是Callable的,如果這兩者檢測都成功了,那么ok,進入下一步。

?? ?(3)構造參數。

?? 方法有了,接下來就缺參數了。參數是以tuple的形式傳遞給方法的,所以我們需要一個PyObject*對象來充當一個Tuple,利用PyTuple_New方法即可。這個方法的參數是tuple內元素的個數,我認為可以理解為參數的個數。由于我的Python代碼只有一個參數,所以這里我直接給1,其他情況可以根據參數的數量賦值。

?? ?然后解釋構建參數了,根據參數的不用類型,可以調用不同的方法。這里由于我在C++程序中的參數是字符串,在Python中的參數也是一個字符串,所以我使用PyString_FromString方法,其中Py是前綴,第一個String指的是在Python代碼中我們需要一個String,也就是目的參數類型,而FromString顧名思義,就是C++中參數的類型。這個方法接受一個參數,也就是一個string,注意,這個string其實是char型數組。返回的結果是一個PyObject*。

?? ?最后一步是要把構造的參數賦值給我們的Tuple,用PyTuple_SetItem方法就可以了。第一個參數是指向Tuple的PyObject指針,第二個參數是value在Tuple中的位置參數,從0開始,最后一個就是咱們的value了,這部分代碼如下:

PyObject *pyParams = PyTuple_New(1); PyObject *pyValue = PyString_FromString(expression.c_str()); PyTuple_SetItem(pyParams, 0, pyValue);
??? (4)調用方法,取返回值。

?? ?好了,大功即將告成~最后一步當然是調用方法了!利用PyObject_CallObject方法,第一個參數是指向函數的那個PyObject指針,第二個參數則是指向我們Tuple的那個PyObject指針。返回值仍然是PyObject指針對象。我們需要對它進行解析,將它轉換成C++的類型。這部分代碼如下:

// ok, call the function pyValue = PyObject_CallObject(pyFunc, pyParams); if(pyValue) {*result = PyFloat_AsDouble(pyValue); // result is a double varreturn true; }
?? ? 好了,到這里調用的全部過程就完成了,其實還不賴。最后,為了方便大家理解,我把整個代碼貼了上來。

?? ?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

?? ?特別說明,如果您是用Python安裝包的形式安裝的Python,那么這個程序只能以Release方式運行!原因是安裝包版Python在libs文件夾下只有Release版的lib文件,而debug模式需要Python26_d.lib,也就是debug模式的。如果您在運行時提示無法打開python26_d.lib文件,那么請換成Release模式,或者下載Python源碼自己編譯,這樣就會生成_d的lib文件了!

?? ?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

?? ?由于我的水平實在有限,文中難免有錯誤,希望各位看到之后留言指正!謝謝各位!

#include <Python.h> // this is in <python-install-path> #include <conio.h> #include <iostream> #include <string>using namespace std;bool calc(string filename, string methodname, string expression, double *result) {PyObject *pyFileName = PyString_FromString(filename.c_str());PyObject *pyMod = PyImport_Import(pyFileName); // load the moduleif (pyMod) // if ok{PyObject *pyFunc = PyObject_GetAttrString(pyMod, methodname.c_str()); // load the functionif (pyFunc && PyCallable_Check(pyFunc)){PyObject *pyParams = PyTuple_New(1);PyObject *pyValue = PyString_FromString(expression.c_str());PyTuple_SetItem(pyParams, 0, pyValue);pyValue = PyObject_CallObject(pyFunc, pyParams); // ok, call the functionif (pyValue){*result = PyFloat_AsDouble(pyValue);return true;}else{return false;}}else{return false;}}else{return false;}return false; }int main(void) {string filename = "python_code"; // filename is settled!string methodname = "calculate"; // method name is also settled!string expression = ""; // get user input!double result = 0.0;printf("\nPlease input the expression: ");getline(cin, expression);// first initPy_Initialize();if (calc(filename, methodname, expression, &result)){printf("\nResult is : %lf\n", result);}else{printf("\nError occurred...\n");}// last fini!Py_Finalize();getch();return 0; }

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的C++调用Python函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。