如何将Python bytes转换为ctypes void指针调用C函数
Python调用C函数传递bytes二进制数据方案
使用ctypes库调用C接口时,针对void*缓冲区+缓冲区长度的函数签名,不需要对bytes对象做UTF-8编码类的字符串转换,按以下两种场景处理即可:
场景1:C函数仅读取缓冲区内容,不会修改内存
ctypes原生兼容bytes类型的参数传递,只要提前声明好函数的参数类型,直接传入bytes对象和len(你的bytes对象)作为长度即可,不会因为二进制数据中包含\x00空字节出现截断问题。场景2:C函数会向传入的缓冲区写入/修改内容
Python的bytes是不可变对象,内存区域只读,直接传入会触发段错误导致进程崩溃,需要先用ctypes.create_string_buffer()申请可写内存,把二进制数据拷贝到缓冲区后再传参。
完整调用示例
import ctypes # 加载编译好的C动态库,Windows替换为.dll后缀,macOS替换为.dylib后缀 c_lib = ctypes.CDLL("./your_c_lib.so") # 必须显式声明函数的参数类型、返回值类型,避免ctypes自动类型推导出错 c_lib.myfunc.argtypes = [ctypes.c_void_p, ctypes.c_int] c_lib.myfunc.restype = ctypes.c_char_p # 从文件读取二进制数据 with open("target_file.bin", "rb") as f: bin_content = f.read() # 只读场景调用 ret = c_lib.myfunc(bin_content, len(bin_content)) # 可写场景调用:创建和原数据等长的可写缓冲区,自动填充原二进制内容 write_buf = ctypes.create_string_buffer(bin_content, len(bin_content)) ret = c_lib.myfunc(ctypes.cast(write_buf, ctypes.c_void_p), len(bin_content)) # 调用完成后,可通过write_buf.raw获取修改后的完整二进制数据 modified_bin = write_buf.raw
注意事项
- 禁止直接将bytes对象传入会修改入参内存的C函数,必现崩溃。
- 必须显式配置
argtypes和restype,否则64位环境下很容易因为指针长度不匹配出现内存访问错误。- 如果C函数要求的缓冲区长度大于当前二进制数据长度,
create_string_buffer初始化时直接传入目标长度即可,超出原数据的内存空间会自动填充0。
内容的提问来源于stack exchange,提问作者K.F. Adams
相关产品推荐
相关产品推荐

