Python的C/C++拓展


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

注意事項

  1. 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)
    
  2. ctypes只兼容C數據類型,如果是C++的擴展程序則需要使用extern "C"進行聲明,若沒有聲明常出現下面的錯誤:
    報錯
    AttributeError: ./test_cpp.so: undefined symbol: add
    
    原因:C和C++經過編譯之後函數命名規則不同,因此會出現符號未定義錯誤。
    正確姿勢
    
    
  3. 默認情況下,假定函數返回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

發佈了32 篇原創文章 · 獲贊 55 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章