近日在作一組聲紋聚類時,使用了另外一團隊同窗開發的聲紋距離算法。該算法對外提供的是一組so包,須要使用方本身去使用。在python中調用純so包通常使用ctypes類庫,用起來看起來簡單但也有很多細節容易犯錯。本次使用過程當中,就遇到傳參的問題。python
目標so庫中對外export的函數是大體以下的三個函數:算法
void* create_handler(); int extract_feature(void* hander); bool destroy(void* handler);
這三個函數使用起來倒也簡單,順序使用就能夠了。但發現寫成以下形式的python代碼後,執行會直接segment fault。函數
import sys import ctypes so = ctypes.CDLL("./lib/libbase.so") p = so.create_handler() feature = so.extract_feature(p) so.destroy(p)
這段代碼中p是int類型,由void*自動轉來,在ctyeps中這種轉型自己是沒問題的。segment fault發生在extract_feature函數調用中,問題應當出在參數上,回傳的handler已經不是原來的pointer了,致使訪問指針出錯。指針
查閱ctypes的文檔後,發現ctypes能夠聲明so庫中函數的參數,返回類型。試了試,顯式聲明後問題獲得瞭解決,證實咱們的猜測是對的,確實指針發生了變化。修改後代碼以下:rest
import sys import ctypes so = ctypes.CDLL("./lib/libbase.so") so.create_handler.restype=ctypes.c_void_p so.extract_feature.argtypes=[ctypes.c_void_p] so.destroy.argtypes=[ctypes.c_void_p] p = so.create_handler() feature = so.extract_feature(p) so.destroy(p)
ctypes中傳遞指針類型參數須要顯式聲明c函數的參數,返回類型。