Cython 使用筆記
前言
最近 bug 改的差不多了,新項目也沒有開始。閑不住,自己又開始折騰,准備使用 Cython 對當前使用的 C 庫進行封裝。目的有以下三個:
- 對該 C 庫的接口及代碼進行初步了解;
- 簡化以后對該 C 庫的單元測試開發;
- 對python和c之間的交互有一個初步了解;
Cython 簡介
Cython 是一門基於 Python 的編程語言, 通過額外的語法允許可選擇的靜態類型聲明。 它的目標是成為 Python 的超集, 而Python 賦予它高級,面向對象,函數式以及動態編程等特性。 使用 Cython 編寫的源代碼會被轉換成優化過的 C/C++ 代碼, 並且被編譯成 Python 的擴展模塊。 這樣即有非常快的程序執行速度和與外部C程序庫的緊密集成, 也可以保持 Python 語言所著稱的高程序員生產力。
本文主要記錄在使用 Cython 過程中遇到的問題。
使用 Cython 過程中的問題
安裝
可以直接下載 windows 二進制安裝包 。
Unable to find vcvarsall.bat
編譯時提示 error: Unable to find vcvarsall.bat 。已經安裝VC,並且將該 bat 文件路徑加入 Path 環境變量也無法解決問題。在 Cython FAQ 中找到解決方案,如果沒有使用 pyximport ,又安裝了 cygwin ,可以在編譯參數加上參數 --compiler=mingw32 來解決問題。
Python undefined reference
編譯時,出現很多錯誤信息如:
undefined reference to `_imp__PyInt_Type'
需要參照 InstallingOnWindows 中的 Troubleshooting,編譯 libpythonXX.a 。(XX 代表 Python 版本號,如 libpython27.a)
- 下載 pexport
- 找到 pythonXX.dll
運行:
pexports pythonXX.dll > pythonXX.def
這樣會提取 pythonXX.dll 的所有符號並將它們寫入 pythonXX.def 。
運行:
dlltool --dllname pythonXX.dll --def pythonXX.def --output-lib > libpythonXX.a
這樣會創建 libpythonXX.a
將 libpythonXX.a 拷入 python 路徑中的 libs 文件夾下。
讀取二進制文件
-
打開文件並讀取所有內容為字符串
data = open("data", "r")
-
將字符串強制轉換為
bytes
,賦值給char*
類型指針cdef char* content = <bytes>data
-
將指針轉換為指定類型傳遞給C庫接口
lib_interface(<TypePTR>content)
導出頭文件宏定義常量
假設在頭文件 interface.h 中存在常量定義:
#define IF_OK 0
將此定義導出需要:
-
需要在 lib.pxd 文件中使用
enum
定義該常量cdef extern from "interface.h": enum: IF_OK
-
在 lib.pyx 文件中:
cimport lib IF_OK = lib.IF_OK
動態內存分配
可以通過:
from libc.stdlib cimport *
使用 malloc
、 free
等 C 標准庫函數