前面2篇分别说了java和c#调用C接口,参数为回调函数,回调函数中参数是结构体指针。
接下来说下python的调用方法。
from ctypes import *
import sys
class 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 = None
def init_sdk():
global _callback_ref
# 包装回调函数
def py_pay_result(p_result):
if not p_result:
print("收到空指针!")
return
try:
# 安全访问结构体内容
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 = 443
return sdk.Init(ip, port, _callback_ref)
if __name__ == "__main__":
init_sdk()
print("SDK初始化完成,等待回调...")
# 保持程序运行(根据实际需求调整)
while True:
pass
这里重要的点是回调函数中,结构体指针是C代码分配的内存,与python有区别,C的结构体中的字段并没有各种方法和属性,需要注意转换。