Python使用ctypes绑定C库时如何正确传递可变指针类型输出参数
问题根因分析
- 输出参数类型定义错误:
algo_encode最后一个入参是algo_hdl_t*,也就是指针的指针,你之前定义argtypes时最后一个参数写了ctypes.c_void_p,类型完全不匹配。 - 输入数据指针传递错误:
from_buffer_copy会复制数据生成新对象,无法指向原输入数据的内存地址,导致C库读取的输入地址非法。 - 输出参数传递方式错误:C代码里需要传
&hdl_enc也就是指针变量的地址,你之前直接传了空指针或者野指针,C库写入目标内存时直接触发段错误。
修复后的完整代码
import ctypes, os from enum import Enum class MessType(Enum): UNKNOWN = 0 EXAMPLE = 1 # 注意:需保证枚举值和C库的algo_type_t定义的枚举值完全对应 def encode(message_type, data): path = os.path.abspath('../../../build/libalgo.dylib') lib = ctypes.CDLL(path) # 修正参数类型定义:最后一个参数是algo_hdl_t*,即指针的指针 lib.algo_encode.argtypes = (ctypes.c_int, ctypes.c_void_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_void_p)) lib.algo_encode.restype = ctypes.c_int # 提前定义free接口的参数类型,后续释放内存要用 lib.algo_free.argtypes = (ctypes.c_void_p,) lib.algo_free.restype = None # 输入数据直接转void*即可,无需额外复制 data_ptr = ctypes.cast(data, ctypes.c_void_p) # 定义handler变量,对应C代码里的algo_hdl_t hdl_enc hdl_enc = ctypes.c_void_p() # 传hdl_enc的地址,等价于C代码的&hdl_enc result = lib.algo_encode(message_type.value, data_ptr, len(data), ctypes.byref(hdl_enc)) print(f"调用返回状态:{result}") # 后续可通过C库的algo_data、algo_data_size接口读取编码后的数据 # 用完必须释放C库分配的内存,避免泄漏 if hdl_enc.value is not None: lib.algo_free(hdl_enc) if __name__ == "__main__": data = b'some_weird_string' # 若C库的encode会根据传入的size读取数据,不需要手动加\x00 encode(MessType.EXAMPLE, data)
关键说明
ctypes.byref(hdl_enc)等价于C语法的&hdl_enc,作用是把指针变量的地址传给C函数作为输出参数,C函数会把分配好的handler地址写入这个变量。- Python的bytes类型可以直接用
ctypes.cast转成c_void_p,ctypes会自动处理内存映射,不需要额外做数据复制。 - 必须显式调用
algo_free释放C库分配的内存,避免出现内存泄漏。
内容的提问来源于stack exchange,提问作者Pierwiastek
相关产品推荐
相关产品推荐

