Python允許使用 C 或 C++ 編寫模塊以使用新模塊來擴展 Python 解釋器的功能。
除了ctypes能夠兼容C數據類型,包裝動態庫以外,還有不少第三方工具提供更簡單或更復雜的方式爲Python創建C和C++的拓展,例如:Cython,Cffi,boost.python,pybind11等等。
ctypes
教程
官方文檔
Calling C/C++ extensions with ctypes
Calling C functions from Python – part 1 – using ctypes – Yi Zhang’s MSDN Blog
注意事項
None
,整型,bytes
對象和字符串(unicode)是僅有的可以直接作爲函數參數使用的四種Python本地數據類型。如果調用函數的傳入參數涉及到其它數據類型,則必須經過顯式的數據類型轉換或顯式指定參數類型,例如:# test.c float add(float x, float y){ return x + y; }
報錯:from ctypes import * libc = CDLL('./test_c.so') res = libc.add(1.2, 1.2) print(res)
解決方案:ctypes.ArgumentError: argument 1: <class 'TypeError'>: Don't know how to convert parameter 1 # 不知道如何轉換數據
或from ctypes import * libc = CDLL('./test_c.so') # 顯式轉換 res = libc.add(c_float(1.2), c_float(1.2)) print(res)
from ctypes import * libc = CDLL('./test_c.so') # 指定參數類型(推薦方式) libc.add.argtypes = [c_float, c_float] res = libc.add(1.2, 1.2) print(res)
ctypes
只兼容C數據類型,如果是C++的擴展程序則需要使用extern "C"
進行聲明,若沒有聲明常出現下面的錯誤:
報錯:
原因:C和C++經過編譯之後函數命名規則不同,因此會出現符號未定義錯誤。AttributeError: ./test_cpp.so: undefined symbol: add
正確姿勢:- 默認情況下,假定函數返回C int類型。 可以通過設置函數對象的restype屬性來指定其他返回類型,例如:
libc.add.restype = c_float
pybind11
pybind11是一個輕量級的頭文件庫,它在Python中暴露C ++類型,反之亦然,主要是創建現有C ++代碼的Python綁定。它的目標和語法與David Abrahams出色的Boost.Python庫相似:通過使用編譯時自檢來推斷類型信息,以最大程度地減少傳統擴展模塊中的模板代碼。
教程
官方文檔
CodeRefinery
Python wrappers for C++ with pybind11 — LSST DM Developer Guide Current documentation