使用C++擴展Python的功能詳解
本文主要研究的是使用C++擴展Python的功能的相關問題,具體如下。
環(huán)境
VS2005Python2.5.4Windows7(32位)
簡介
長話短說,這里說的擴展Python功能與直接用其它語言寫一個動態(tài)鏈接庫,然后讓Python來調(diào)用有點不一樣(雖然本質(zhì)是一樣的)。而是指使用Python本身提供的API,使用C++來對Python進行功能性擴展,可以這樣理解,使用更高效的語言實現(xiàn)一些算法計算等等需要更高執(zhí)行效率的核心(或者需要與系統(tǒng)進行密切交互的)模塊,然后讓Python像調(diào)用內(nèi)建標準庫的方式來調(diào)用這些模塊,聽起來是不是很誘人?!在軟件技術高速發(fā)展的今天,借助幾種計算機語言來實現(xiàn)一個系統(tǒng)的例子數(shù)不勝數(shù),目的不外乎就是性能和便利的平衡。譬如本文要討論的使用C++來擴展Python就是Python和C++的一種巧妙的有機結(jié)合,好處不言而喻,既可以獲得和C++相似的執(zhí)行性能,又可以利用Python的開發(fā)靈活性。由于Python本身是使用C實現(xiàn)的,二者結(jié)合起來還是比較容易的。
基本流程
本文不適合這樣的讀者——對Python完全不了解或者對C\C++完全不了解,道理你們懂的。另外就是Python里面有6種基本數(shù)據(jù)類型。你需要了解如何在C和Python之間對這些類型進行轉(zhuǎn)化(這不在本文討論范圍,可以參考[1])。
言歸正傳,感覺前面說得太多了,實際上很簡單,因此我決定少說多做。一個C++的Python擴展模塊至少應該有導出函數(shù),方法列表和初始化函數(shù)三個部分。我們用VS2005這個強大的工具開工!一般來說,你應該建一個Dll工程(至于使用exe來擴展Python可以不可以,暫時還沒研究過)。下面按部就班的說明(關鍵說明在注釋部分)。
一、初始化函數(shù)
//------------------------------------------------------------------------- // 函數(shù) : initPyExt // 功能 : 初始化函數(shù) // 返回值 :PyMODINIT_FUNC // 附注 : 注意,這個函數(shù)的名字不能改動。必須是init+模塊名字, // 我們的模塊名字是PyExt,所以函數(shù)名是initPyExt。Python在導入 // 我們的PyExt模塊時,會找到這個函數(shù),并調(diào)用。這個函數(shù)實現(xiàn)的 // 功能很簡單,通過調(diào)用Py_InitModule將模塊名字和映射表結(jié)合起 // 來,它的意思是說PyExt這個模塊使用PyExtMethods這個映射表。 //------------------------------------------------------------------------- PyMODINIT_FUNCinitPyExt() { Py_InitModule("PyExt",PyExtMethods); }
二、方法列表
/* 方法列表,這個是一個C結(jié)構(gòu)數(shù)組。把需要擴展的函數(shù)都映射到這個表里。 那么Python就知道你的這個擴展模塊支持一些什么方法了。表的第一個字 段是方法名字,也是通過Python來調(diào)用時的名字。第二個字段是導出函數(shù), 是真正調(diào)用的函數(shù),也是C\C++實現(xiàn)的函數(shù)。第三個參數(shù)是指明Python向 C\C++函數(shù)傳遞參數(shù)的形式。可選的兩種方式是METH_VARARGS和 METH_KEYWORDS,其中METH_VARARGS是參數(shù)傳遞的標準形式,它通 過Python的元組在Python解釋器和C函數(shù)之間傳遞參數(shù),若采用 METH_KEYWORD方式,則Python解釋器和C函數(shù)之間將通過Python的字典 類型在兩者之間進行參數(shù)傳遞。第四個字段是這個函數(shù)的說明。如果你在 python里來help這個函數(shù),將顯示這個說明。相當于在python里的函數(shù)的文檔說明。 */ staticPyMethodDefPyExtMethods[]= { {"Add", Add,METH_VARARGS,"Addtwo number - edit by magictong."}, {"ExecSystem",ExecSystem,METH_VARARGS,"Execute a shell command - edit bymagictong." }, {NULL,NULL, 0,NULL} };
三、導出函數(shù)
//------------------------------------------------------------------------- // 函數(shù) : Add // 功能 : 這是一個加法函數(shù) // 返回值 :PyObject* // 參數(shù) : PyObject*self 這個參數(shù)我們暫時不用理會 // 參數(shù) : PyObject*args 是一個參數(shù)列表,我們需要從它解析出參數(shù) // 附注 : // 所有的導出函數(shù)都具有相同的原型: // PyObject*method(PyObject* self, PyObject* args); //PyArg_ParseTuple來完成解析參數(shù)任務。它的第一個參數(shù)是args, // 就是我們要轉(zhuǎn)換的參數(shù)。第二個是格式符號。"s"代表是個string。 // 從args里提取一個參數(shù)就寫"s",兩個的話就寫"s|s",如果是一個 // string,一個int,就寫"s|i",有點和printf類似哦。第三個參數(shù)就是 // 提取出來的參數(shù)放置的真正位置。必須傳遞這個參數(shù)的地址。 //------------------------------------------------------------------------- staticPyObject*Add(PyObject*self,PyObject*args) { intx = 0 ; inty = 0; intz = 0; if(!PyArg_ParseTuple(args,"i|i", &x, &y)) returnNULL; z=x +y; returnPy_BuildValue("i",z); /* 調(diào)用完之后我們需要返回結(jié)果。這個結(jié)果是c的type或者是我們自己定義的類型。 必須把他轉(zhuǎn)換成PyObject,讓python認識。這個用Py_BuildValue來完成。他 是PyArg_ParseTuple的逆過程。他的第一個參數(shù)和PyArg_ParseTuple的第二個 參數(shù)一樣,是個格式化符號。第三個參數(shù)是我們需要轉(zhuǎn)換的參數(shù)。Py_BuildValue 會把所有的返回只組裝成一個tutple給python。 如果對應的C函數(shù)沒有返回值(即返回值類型為void),則應返回一個全局的None 對象(Py_None),并將其引用計數(shù)增,如下所示: Py_INCREF(Py_None); returnPy_None; */ }
四、再加點功能
intcmd(constchar* arg) { returnsystem(arg); } staticPyObject*ExecSystem(PyObject*self,PyObject*args) { constchar*command; if(!PyArg_ParseTuple(args,"s", &command)) returnNULL; intn =cmd(command); returnPy_BuildValue("i",n); }
編譯
開編,編譯出來的PyExt.dll文件改名為PyExt.pyd放入Python的C:\Python25\DLLs目錄就可以全局使用了,如果你只想某個Python的工程,放在工程的相對路徑下面就可以了。
使用
可能的問題
里面的這些PyMODINIT_FUNC,與Python相關的宏和定義在哪里呢?定義下#include<Python.h>就可以了,但是定義了之后提示Python.h找不到還是編譯不過怎么辦?這說明你沒有安裝Python或者安裝了但是沒有把頭文件路徑引入Path環(huán)境變量,或者你把Python的include目錄加入工程的附加包含目錄(Additional IncludeDirectories),一般是C:\Python25\include這個目錄,其中C:\Python25是Python的安裝目錄,按你機器的實際情況配置)。
如果提示:Error 1 fatal error LNK1104:cannot open file 'python25_d.lib' 類似這樣的錯誤,一般可能是沒有安裝Python的開發(fā)版本,沒關系,你使用Release編譯一下,如果還不行,就把C:\Python25\libs目錄加入工程的附加庫目錄(Additional LibraryDirectories)。
總結(jié)
以上就是本文關于使用C++擴展Python的功能詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關文章
Python?GUI利用tkinter皮膚ttkbootstrap實現(xiàn)好看的窗口
這篇文章主要介紹了Python?GUI利用tkinter皮膚ttkbootstrap實現(xiàn)好看的窗口,文章基于python的相關資料展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下2022-06-06Python數(shù)據(jù)分析之?Pandas?Dataframe修改和刪除及查詢操作
這篇文章主要介紹了Python數(shù)據(jù)分析之?Pandas?Dataframe修改和刪除及查詢操作的相關資料,具有一定的參考價值,需要的小伙伴可以參考一下2022-05-05淺談python元素如何去重,去重后如何保持原來元素的順序不變
這篇文章主要介紹了淺談python元素如何去重,去重后如何保持原來元素的順序不變?具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02python通過opencv實現(xiàn)圖片裁剪原理解析
這篇文章主要介紹了python通過opencv實現(xiàn)圖片裁剪原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-01-01