-
1 # 張羽赫
-
2 # 小小猿愛嘻嘻
你說的是在C/C++程式中呼叫Python吧,這個實現起來非常簡單,只需要在標頭檔案中引入Python.h檔案,然後在編譯的時候連結到Python庫即可,下面我簡單介紹一下,以Linux系統為例,感興趣的朋友可以嘗試一下:
01安裝python-devel外掛首先,安裝python-devel外掛,這個外掛包含有C/C++程式呼叫Python的標頭檔案和庫檔案,在編寫和編譯程式的時候會用到,安裝的話,直接在終端輸入命令“yum install -y python-devel”即可,預設情況下安裝的是Python2,需要安裝Python3.x的話,執行命令“yum install -y python3x-devel”即可:
02C/C++程式呼叫Python外掛安裝完成後,我們就可以直接編寫C/C++程式來呼叫Python了,測試程式碼如下,這裡我簡單輸出了一條Python語句,基本思想先初始化,然後呼叫Python,最後再結束,整個流程非常簡單,也非常容易理解:
編寫完成後,wq儲存程式,接著在終端執行“gcc -lpython2.7 test.c -o test”命令(這裡替換成你的C/C++檔案),即可正常編譯程式,執行效果如下,和預期的一樣:
當然,你也可以直接呼叫py檔案(指令碼),傳入引數,取得返回結果,這裡我簡單編寫了一個add求和函式,輸入2個引數,返回一個結果:
C/C++呼叫程式碼如下,基本流程和前面一樣,先初始化,然後載入模組,呼叫函式,傳入引數,最後再取得執行結果,程式碼量有些多,但理解起來不難:
至此,我們就完成了在C/C++程式中呼叫Python。總的來說,整個過程非常簡單,只要你有一定C/C++基礎,熟悉一下上面的示例和程式碼,很快就能掌握的,Windows環境類似,也需要匯入對應標頭檔案和庫,網上也有相關教程和資料,介紹的非常詳細,感興趣的話,可以搜一下,希望以上分享的內容能對你有所幫助吧,也歡迎大家評論、留言進行補充。
-
3 # 你看我獨角獸嗎
如果要在Python中包裝現有的C或C ++功能,則有很多選擇可以去做。一個比較簡單的是,我們可以試著手動封裝嘗試下如何用Python嵌入C/C++進行開發。
手動封裝如果您要包裝的C / C ++程式碼相對較少,則可以手動完成。文件的“ 擴充套件和嵌入”部分是一個很好的參考。
當我為C和C ++程式碼編寫包裝器時,通常會為程式碼提供一個過程介面,然後使用Python構造一個面向物件的介面。我這樣做是出於兩個原因:首先,將C ++物件暴露給Python很麻煩;其次,我更喜歡用Python編寫高層結構,而不是用C ++編寫它們。
讓我們看一個基本的包裝器:檔案“ hello.c”中有一個函式“ hello”。“ hello”的定義如下:
char * hello(char * what)要手動封裝,我們需要執行以下操作。
首先,編寫一個Python可呼叫函式,該函式接受一個字串並返回一個字串。
其次,在模組的符號表中註冊此函式(所有Python函式都存在於模組中,即使它們實際上是C函式也是如此!)
第三,為模組編寫一個初始化函式(所有擴充套件模組都需要一個初始化函式)。
第四,編寫一個setup.py指令碼:
錯誤處理請注意PyArg_ParseTuple呼叫。該呼叫告訴Python,“ hello”包裝函式恰好採用一個引數,即字串(“ s”表示“字串”;“ ss”表示“兩個字串”;“ si”表示“字串和整數”)) 。C API與Python的約定是,從返回PyObject *的函式返回NULL表示已發生錯誤;在這種情況下,錯誤資訊是在PyArg_ParseTuple中設定的,我們只是透過返回NULL在堆疊上傳遞錯誤。
引用計數Python在引用計數系統上工作:每當一個函式“擁有”一個物件的所有權(例如,透過將其分配給列表或字典),它都會使用Py_INCREF使該物件的引用計數增加1。當將該物件從該特定位置刪除(例如,從列表或字典中刪除)時,引用計數將使用Py_DECREF減少。當引用計數達到0時,Python會知道該物件未被任何物件使用,並且可以釋放該物件(但是,可能不會立即釋放它)。
為什麼這麼重要?好吧,我們正在用PyString_FromString在此程式碼中建立一個PyObject。我們需要INCREF嗎?要找出答案,請檢視PyString_FromString的文件:
http://docs.python.org/api/stringObjects.html#l2h-461看到哪裡寫著“新參考”?這意味著它將交出引用計數為1的物件,這就是我們想要的。如果它說“借用的引用”,那麼我們需要在返回物件之前先對物件進行INCREF,以表明我們希望分配的記憶體能夠在函式結束後繼續存在。
這是一種考慮引用的方法:
如果您從Python API收到Python物件,則可以在自己的C程式碼中使用它,而無需增加它的引用。
如果您想保證Python物件可以在您自己的C程式碼末尾保留下來,則必須INCREF。
如果您從Python程式碼收到一個物件,並且它是一個新引用,但是您不希望它在您自己的C程式碼末尾生存下來,則應該對它進行DECREF。
順便說一句,如果您想返回None,則可以使用Py_None。記住要INCREF!
另一個注意事項:我談到了使用PyCObjects傳遞不透明的C / C ++資料型別。如果您使用Python來組織程式碼,但是這具有不需要訪問Python的複雜結構,則這很有用。
您可以將指標包裝在PyCObjects中(如果需要,可以使用關聯的解構函式),此時它們變為不透明的Python物件,其記憶體由Python直譯器管理
。可以在示例程式碼看到一個例子,下 code/hello/hellmodule.c,函式cobj_in,cobj_out以及 free_my_struct,它透過使用PyCObject包裝的分配的C結構回到Python。
總結因此,這是關於如何手動封裝Python的簡短介紹。但是,您可能會猜到,有許多專案專門用於自動封裝程式碼。所以手動封裝嘗試下用Python嵌入C/C++進行開發,其他的大家可以搜尋看看,比較好用的是SWIG、pyrex和ctypes的等。
回覆列表
如果你想把Python嵌入C C++中是比較簡單的事情,你需要的是在VC中新增Python的include檔案目錄和lib檔案目錄。下面我們來看下如何把Python
如果你想把Python嵌入C/C++中是比較簡單的事情,你需要的是在VC中新增Python的include檔案目錄和lib檔案目錄。下面我們來看下如何把Python嵌入C/C++中。
VC6.0下,開啟 tools->options->directories->show directories for,將Python安裝目錄下的inlude目錄新增到inlude files項中,將libs目錄新增到library files項中。
VC2005下,開啟tools->options->專案和解決方案->VC++目錄,然後做相同工作。
程式碼如下:
在debug下執行出錯,“無法找到python31_d.lib檔案”,後查到原因是:在debug下生成必須要有python31_d.lib檔案,否則只能在release下生成
#include <python.h>
int main()
{
Py_Initialize();
PyRun_SimpleString("Print "hi, python!"");
Py_Finalize();
return 0;
}
Py_Initialize函式原型是:void Py_Initialize()
把Python嵌入C/C++中時必須使用該函式,它初始化Python直譯器,在使用其他的Python/C API之前必須先呼叫該函式。可以使用Py_IsInitialized函式判斷是否初始化成功,成功返回True。
PyRun_SimpleString函式原型是int PyRun_SimpleString(const char *command),用來執行一段Python程式碼。
注意:是否需要維持語句間的縮排呢?
Py_Finalize函式原型是void Py_Finalize(),用於關閉Python直譯器,釋放直譯器所佔用的資源。
PyRun_SimpleFile函式可以用來執行".py"指令碼檔案,函式原型如下:
int PyRun_SimpleFile(FILE *fp, const char *filename);
其 中fp是開啟的檔案指標,filename是要執行的python指令碼檔名。但是由於該函式官方釋出的是由visual studio http://2003.NET編譯的,如果使用其他版本的編譯器,FILE定義可能由於版本原因導致崩潰。同時,為簡便起見可以使用如下方式來代替該函式:
PyRun_SimpleString("execfile(‘file.py’)"); //使用execfile來執行python檔案
Py_BuildValue()用於對數字和字串進行轉換處理,變成Python中相應的資料型別(在C語言中,所有Python型別都被宣告為PyObject型別),函式原型如下:
PyObject *Py_BuildValue(const char *format, …..);
PyString_String()用於將PyObject*型別的變數轉換成C語言可以處理的char*型,具體原型如下:
char* PyString_String(PyObject *p);