Python擴展(Cython混編)


  • 背景介紹
    Cython是一種針對Python語言與Cython擴展語言進行優化的靜態編譯器通過編寫Cython接口代碼,可以讓Python代碼與C/C++代碼無縫銜接,達到為Python加速的目的。當然,也可以完全通過Cython接口重構Python代碼,直接提速Python。整個過程可以表示為:首先將Cython接口代碼轉化為C/C++代碼,然后將C/C++代碼編譯為動態鏈接庫.pyd(Windows下)或.so文件(Linux下),即:
    Cython接口代碼 $\rightarrow$ C/C++代碼 $\rightarrow$ .pyd/.so動態庫
    如果接口編寫得當,通過Python調用該動態庫文件較原生Python代碼可提速兩個量級。
    在語法層面,Cython幾乎支持所有的Python語法,並且額外加入了一些C/C++的等效寫法(提速的關鍵)。因此,在編寫接口代碼的時候勢必兩種寫法都會用到,從而造成混亂。本文將主要介紹筆者習慣的Cython接口寫法規范,可能會比較抽象。關於語法細節,建議參考官方文檔:https://cython.org/

  >>>使用規范<<<

  • Python接口端實現Cython與Python之間的交互支持缺省參數
    • def $\rightarrow$ 函數接口
    • cdef class $\rightarrow$ 類接口
      此種情況下,類對象中self只能索引已存在的對象,不能直接創建新內容,功能上與this指針基本對標,此即self限制(只能索引已經定義的對象)。
    注意,不建議采用純粹的class作為接口(因為健康的Python語法解除了對self的限制,從而無法與this指針對標,進而找不到C++對象並無法與C++對象直接映射),此種用法可以作為純Python加速方案考慮。Python接口端異常可以自動傳遞
  • C++接口端實現Cython與C++之間的交互不支持缺省參數
    • cdef $\rightarrow$ 函數接口
    • cdef struct $\rightarrow$ 類接口,不支持函數重載
    • cdef cppclass $\rightarrow$ 類接口,支持函數重載注意,Cython內部支持引用"&"與指針"*"操作,支持常量"const"限定(但const可以忽略)。
    注意,C++接口端異常需要手動傳遞推薦使用"except +")。
  • 常見操作
    • 頭部編譯指令
      # cython: language_level=3    # 指定Python版本
      # distutils: language=c++     # 指定C++編譯
    • 加載Cython模塊
      from libcpp.vector cimport vector
      from libcpp.string cimport string
      注意,vector映射Python中的Iterable對象,string映射Python中bytes對象。
    • 加載外部C++頭文件及源文件
      cdef extern from '*.h':
          ...
      cdef extern from '*.cpp':
          pass
      注意,加載頭文件是為了獲取聲明信息,加載源文件是為了獲取定義信息。必須保證聲明信息具有相應的定義內容(即實體)
  • 細節問題
    • setup.py文件中,sources參數必須保證加載到所有涉及到的C++源文件,但是不能重復加載;include_dirs參數可以附加包含目錄
    • 當需要實例化一個C++接口下的類時,必須確保該類至少持有默認構造函數
      C++實例訪問:
      直接訪問 $\rightarrow$ 通過實例 $\rightarrow$ 類持有默認構造函數
      間接訪問 $\rightarrow$ 通過指針 $\rightarrow$ 動態開辟空間注意內存釋放(__dealloc__)
    • 采用cdef聲明C++數據類型時需要注意:C++接口端類內部以及所有形參列表中均不能添加cdef關鍵字,其它地方均建議添加cdef關鍵字
      同時,無類型聲明的對象默認為Python對象類型可以通過Python對象類型向接口內部傳入str對象,再在合適的地方轉換為bytes對象
    • 采用bint類型代替bool類型
    • Cython接口層級划分參考:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM