python基础-C扩展
寫python的c擴展簡介
使用C/C++編寫Python模塊擴展
Python - 用C擴展編程
使用 C 或 C++ 擴展 Python
原因
- 添加額外的非python功能。
- 性能瓶頸的效率提升
- 專有源代碼保密
寫擴展庫的代碼
Extest.c文件包含包含要擴展的C模塊,包含fac()和reverse()函數。
并調試完bug。
包裝代碼
- 包含python頭文件
- 為每個模塊的每個函數增加一個Pyobject * Module_func()的包裝函數
- 為每個模塊增加一個PyMethodDef ModuleMethods[]的數組
- 增加木塊初始化函數void initModule()
為想被Python環境訪問的函數增加一個靜態變量,函數的返回值類型為PyObject*,函數名前要加上模塊名和一個下劃線。比如Extest模塊的fac函數,創建包裝函數Extest_fac()。這樣可以在python中import Extest,然后調用Extest.fac()。
包裝函數就是把Python的值傳遞給C,然后調用C函數處理。當處理完成返回給python的時候,把函數的計算結果轉換成python對象,返回給python。
從python到C的轉換用PyArg_Parse*系列函數。從C轉到python的時候,就用Py_BuildValue()函數。
PyArg_Parse系列函數用法跟C的sscanf 函數很像,接受一個字符串流,根據一個指定格式字符串進行解析,把結果放入到相應的指針所指的變量中。返回值為1表示解析成功,返回值為0表示失敗。
Py_BuildValue的用法跟sprintf函數很像,把所有的參數按格式字符串所指定的格式轉換成一個python對象。
| int PyArg_ParseTuple() | 把python傳過來的參數轉為C |
| int PyArg_ParseTupleAndKeywords() | 把python傳過來的參數轉為C,但是同時解析關鍵字參數 |
| PyObject *Py_BuildValue() | 把C的數據轉為python的一個對象或一組對象,然后返回 |
python和C數據轉換的格式符號
| s | str | char * |
| z | str/None | char * /NULL |
| i | int | int |
| l | long | long |
| c | str | char |
| d | float | double |
| D | complex | Py_Complex * |
| O | (any) | PyObject * |
| S | str | PyStringObject |
‘ss’格式讓Py_BuildValue()函數生成了一個包含兩個字符串的tuple。
C代碼中注意內存泄露。復制字符串后在函數退出前要釋放。
為每個模塊增加PyMethodDef ModuleMethods[]數組
完成包裝函數后,需要把函數列在某個地方,編譯python解釋器能夠導入并調用。
這是個二維數組,里面每個數組包含一個函數,最后放一個NULL數組表示列表的結束。
增加模塊初始換函數void initModule()
調用Py_InitModule()函數,并把模塊名和ModuleMethods[]數組的名字穿進去。
編譯
- 創建setup.py
- 通過運行setup.py來編譯和連接代碼
- 從python中導入擴展模塊
創建setup.py,編譯主要由setup()函數完成。這個函數調用之前的所有代碼。每個擴展模塊需要一個Extension實例。
Extension(MOD,sources=['Extest.c'])
名字為模塊名,sources參數是所有源代碼的文件列表。
setup()函數第一個參數表示要編譯哪些東西,一個列表列出要編譯的對象。
編譯和連接代碼
運行setup.py build命令可以開始編譯我們的擴展了。
導入和測試
擴展會被創建在運行setup.py腳本所在的目錄下的build/lib.*目錄下。可以切換到哪個目錄中測試新木塊,也可以使用命令安裝到python中
然后就可以在python中導入和使用模塊中的函數了。
總結
以上是生活随笔為你收集整理的python基础-C扩展的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySql服务无法连接
- 下一篇: python基础-类