C語言和Python一起混合編程?兩者相加無敵了!(文末附教分享)
C語言是編程語言的祖母,但是隨著一代一代的編程語言長大,所以祖母也是會拍在沙灘上的,很多小小夥伴應該都會學過或者瞭解C語言,因為軟件系的會教嘛,但是Pytho很多人都沒學過,下面給大家介紹下,C語言和Python一起混合編程會產生什麼不一樣的火花吧!
1、C/C 調用Python(基礎篇)
在Mac OS X 下的編譯命令同上
產生可執行文件後,直接運行,結果為輸出
Hello Python!
Python庫函數PyRun_SimpleString可以執行字符串形式的Python代碼。雖然非常簡單,但這段代碼除了能用C語言動態生成一些Python代碼之外,並沒有什麼用處。我們需要的是C語言的數據結構能夠和Python交互。
下面舉個例子,比如說,有一天我們用Python寫了一個功能特別強大的函數:
從上述代碼可以窺見Python內部運行的方式:
所有Python元素,module、function、tuple、string等等,實際上都是PyObject。C語言裡操縱它們,一律使用PyObject *。
Python的類型與C語言類型可以相互轉換。Python類型XXX轉換為C語言類型YYY要使用PyXXXAsYYY函數;C類型YYY轉換為Python類型XXX要使用PyXXXFromYYY函數。
也可以創建Python類型的變量,使用PyXXX_New可以創建類型為XXX的變量。
若a是Tuple,則a[i] = b對應於 PyTupleSetItem(a,i,b),有理由相信還有一個函數PyTupleGetItem完成取得某一項的值。
不僅Python語言很優雅,Python的庫函數API也非常優雅。
現在我們得到了一個C語言的函數了,可以寫一個main測試它
編譯的方式就用本節開頭使用的方法。
在Linux/Mac OSX運行此示例之前,可能先需要設置環境變量:
bash:
export PYTHONPATH=.:$PYTHONPATH
csh:
setenv PYTHONPATH.:$PYTHONPATH
2 Python 調用 C/C (基礎篇)
這種做法稱為Python擴展。
比如說,我們有一個功能強大的C函數
除了功能強大的函數great_function外,這個文件中還有以下部分:
包裹函數greatfunction。它負責將Python的參數轉化為C的參數(PyArgParseTuple),調用實際的greatfunction,並處理great_function的返回值,最終返回給Python環境。
導出表GreateModuleMethods。它負責告訴Python這個模塊裡有哪些函數可以被Python調用。導出表的名字可以隨便起,每一項有4個參數:第一個參數是提供給Python環境的函數名稱,第二個參數是greatfunction,即包裹函數。第三個參數的含義是參數變長,第四個參數是一個說明性的字符串。導出表總是以結束。
導出函數initgreat_module。這個的名字不是任取的,是你的module名稱添加前綴init。導出函數中將模塊名稱與導出表進行連接。
在Windows下面,在Visual Studio命令提示符下編譯這個文件的命令是
3、C/C 調用Python(使用Cython)
這其中有非Python關鍵字cdef和public。這些關鍵字屬於Cython。由於我們需要在C語言中使用“編譯好的Python代碼”,所以得讓great_function從外面變得可見,方法就以“public”修飾。而cdef類似於Python的def,只有使用cdef才可以使用Cython的關鍵字public。
這個函數中其他的部分與正常的Python代碼是一樣的。
接下來編譯 great_module.pyx
編譯命令和第一部分相同:
在Windows下編譯命令為
在Visual Studio命令提示符下編譯:
cl/LD dllmain.cgreat_module.c-IC:Python27includeC:Python27libspython27.lib
會得到一個dllmain.dll。我們在Excel裡面使用它,沒錯,傳說中的Excel與Python混合編程:
參考資料:Cython的官方文檔
4、Python調用C/C (使用SWIG)
接下來使用SWIG將這個配置文件編譯為所謂Python Module Wrapper
swig-python mymodule.i
得到一個 mymodule_wrap.c和一個mymodule.py。把它編譯為Python擴展:
Windows:
cl/LD mymodule_wrap.c/o_mymodule.pyd-IC:Python27includeC:Python27libspython27.lib
Linux:
gcc-fPIC-shared mymodule_wrap.c-o_mymodule.so-I/usr/include/python2.7/-lpython2.7
注意輸出文件名前面要加一個下劃線。
現在可以立即在Python下使用這個module了:
換句話說,SWIG自動完成了諸如Python類型轉換、module初始化、導出代碼表生成的諸多工作。
對於C ,SWIG也可以應對。例如以下代碼有C 類的定義:
寫在最後:
由於CPython自身的結構設計合理,使得Python的C/C 擴展非常容易。如果打算快速完成任務,Cython(C/C 調用Python)和SWIG(Python調用C/C )是很不錯的選擇。但是,一旦涉及到比較複雜的轉換任務,無論是繼續使用Cython還是SWIG,仍然需要學習Python源代碼。