前面2篇分別說了java和c#調用C接口,參數為回調函數,回調函數中參數是結構體指針。
接下來說下python的調用方法。
from ctypes import *
import sysclass stPayResult(Structure):_pack_ = 4 # 根據實際C結構體的對齊方式設置(常見值為1,4,8)_fields_ = [("place", enPlace),("errCode", c_char_p),("errInfo", c_char_p),("seqId", c_char_p),("merOrderId", c_char_p),("srcReserve", c_char_p),("attachedData", c_char_p),("totalAmount", c_char_p),("couponAmount", c_char_p),("payAmount", c_char_p),("payTime", c_char_p),("orderCreateTime", c_char_p),("status", c_char_p)]# 定義回調類型(嚴格匹配C函數調用約定)
OnPayResult = CFUNCTYPE(None, POINTER(stPayResult))# 加載C庫(示例使用Windows DLL)
try:sdk = CDLL("./xxx.dll") # 替換為實際庫路徑
except Exception as e:print(f"加載動態庫失敗: {str(e)}")sys.exit(1)# 嚴格設置函數原型
sdk.Init.argtypes = [c_char_p, c_ushort, OnPayResult]
sdk.Init.restype = c_size_t# 保持回調函數引用防止GC
_callback_ref = Nonedef init_sdk():global _callback_ref# 包裝回調函數def py_pay_result(p_result):if not p_result:print("收到空指針!")returntry:# 安全訪問結構體內容result = p_result.contents# 處理可能為NULL的字符串err_code = result.errCode.decode() if result.errCode else ""err_info = result.errInfo.decode() if result.errInfo else ""print(f"錯誤碼: {err_code}, 錯誤信息: {err_info}")except Exception as e:print(f"處理回調時發生異常: {str(e)}")# 轉換為C回調并保持引用_callback_ref = OnPayResult(py_pay_result)# 調用初始化ip = b"127.0.0.1"port = 443return sdk.Init(ip, port, _callback_ref)if __name__ == "__main__":init_sdk()print("SDK初始化完成,等待回調...")# 保持程序運行(根據實際需求調整)while True:pass
這里重要的點是回調函數中,結構體指針是C代碼分配的內存,與python有區別,C的結構體中的字段并沒有各種方法和屬性,需要注意轉換。