前面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的结构体中的字段并没有各种方法和属性,需要注意转换。