You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过ctypes传递numpy字节数组给接收void*的C函数报错求解决

解决numpy字节数组通过ctypes传递给C void*参数的问题

哦,这个坑我踩过!你遇到的AttributeError是因为你把numpy数组转换成了Python原生的bytes对象——原生bytes根本没有ctypes属性,只有numpy数组本身才自带这个接口来直接获取内存地址。

给你两个可行的解决方案,优先选第一个,效率更高:

方案一:直接使用numpy数组的ctypes属性(推荐)

不需要把数组转成bytes,直接用numpy数组自带的ctypes.data_as()方法获取内存地址,这样C函数可以直接访问numpy的内存缓冲区,没有数据拷贝:

import numpy as np
import ctypes

# 1. 先加载你的C库并定义函数参数(示例)
# 假设你的C函数签名是:void process_data(void* mem_addr, int rows, int cols, int elem_size)
your_lib = ctypes.CDLL("./your_c_library.so")  # 替换成你的库路径
process_data = your_lib.process_data
# 一定要指定参数类型,避免ctypes自动推导出错
process_data.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int]
process_data.restype = None

# 2. 创建numpy数组(建议明确指定dtype,避免跨平台类型差异)
lst = np.random.choice(np.arange(0, 100, dtype=np.int32), size=(100, 5))

# 3. 获取数组的内存地址并传递给C函数
mem_address = lst.ctypes.data_as(ctypes.c_void_p)
# 同时要把数组的维度、元素大小传给C函数,不然C不知道怎么解析这块内存
process_data(mem_address, lst.shape[0], lst.shape[1], lst.itemsize)

注意点:

  • 确保numpy数组的dtype和C函数预期的类型一致(比如C用int32_t,numpy就用np.int32),否则会出现数据解析错误。
  • 调用C函数期间,不要让numpy数组被Python垃圾回收(比如不要提前删除变量或者让它超出作用域),否则C函数访问的内存会变成无效内存。

方案二:用ctypes缓冲区包装bytes(适合特殊场景)

如果确实需要先把数组转成bytes,可以用ctypes.create_string_buffer把bytes包装成一个可获取地址的缓冲区:

import numpy as np
import ctypes

lst = np.random.choice(np.arange(0, 100, dtype=np.int32), size=(100, 5))
lst_bytes = lst.tobytes()

# 创建ctypes缓冲区,把bytes数据拷贝进去
buffer = ctypes.create_string_buffer(lst_bytes)
# 把缓冲区转换成void*类型
mem_address = ctypes.cast(buffer, ctypes.c_void_p)

# 同样传递给C函数,附带必要的元数据
process_data(mem_address, lst.shape[0], lst.shape[1], lst.itemsize)

这个方法会额外拷贝一次数据,效率不如第一种,所以只在必须用bytes的场景下使用。

内容的提问来源于stack exchange,提问作者steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:26:53