NumPy数组ndarray.data与ndarray.ctypes.data的区别探究
问题:NumPy数组的
.data与.ctypes.data区别解析 我有一个C数组想要在Python中使用,通过pybind11将该C数组暴露为原始内存缓冲区,C++代码如下:
#include <pybind11/pybind11.h> #include <pybind11/numpy.h> namespace py = pybind11; py::memoryview create_cpp_owned() { const double *dynamic_c_array = new double[4]{0, -1.2, 3.24, 9.0}; std::cout << "Memory address of the C array: " << dynamic_c_array; return py::memoryview::from_memory(dynamic_c_array, sizeof(double) * 4); }
随后在Python中调用create_cpp_owned函数(raw_data为memoryview对象):
print('Creating a direct accessor to a C++ buffer (memory owned by C++)...') raw_data = create_cpp_owned() print(f'Address of the raw data: {raw_data}') # or: print(hex(id(raw_data))) np_view = np.frombuffer(raw_data, dtype=np.float64) print(f'NumPy view on this data: "np_view" = {np_view}') print(f'Address of "np_view": {hex(np_view.ctypes.data)}') print(f'Note that np_view.data does not return the same address: {np_view.data}') print(f'Python does not own the memory: np_view.flags["OWNDATA"] = {np_view.flags["OWNDATA"]}')
运行输出如下:
Creating a direct accessor to a C++ buffer (memory owned by C++)... Memory address of the C array: 0x55af59d39590 Address of the raw data: <memory at 0x14a9af19f640> NumPy view on this data: "np_view" = [ 0. -1.2 3.24 9. ] Address of "np_view": 0x55af59d39590 Note that np_view.data does not return the same address: <memory at 0x14a99f3aa280> Python does not own the memory: np_view.flags["OWNDATA"] = False
可以看到np_view.data未返回底层C数组的正确地址,而np_view.ctypes.data返回了。那么对于NumPy数组来说,.data和.ctypes.data到底分别代表什么?
回答
1. np.ndarray.data
data属性返回的是Python memoryview对象,它是对NumPy数组底层内存的包装视图。- 输出中的
<memory at 0x14a99f3aa280>是这个memoryview对象本身在Python堆中的地址,而非底层C数组的内存地址。 - 该memoryview的作用是让Python代码通过缓冲区协议访问数组数据,但它本身是独立的Python对象,有自己的内存空间。
2. np.ndarray.ctypes.data
ctypes.data返回的是底层数据缓冲区的原始C风格内存地址(整数类型),直接对应C++中分配的数组内存(比如示例中的0x55af59d39590)。- 它本质是直接获取NumPy数组底层指针指向的起始地址,是数据实际存储的位置。
- 当NumPy数组是外部内存的视图(如通过
np.frombuffer创建的非自有数据数组),这个属性能准确拿到外部数据的真实地址。
关键区别总结
.data是Python层面的内存视图对象,显示的是对象自身的地址,而非数据的存储地址。.ctypes.data直接返回底层数据的C内存地址,是数据实际存放的位置。
内容的提问来源于stack exchange,提问作者Zoltan Csati
相关产品推荐
相关产品推荐

