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

如何通过Pybind11从py::memoryview获取py::buffer_info及数组元信息?

在Pybind11中从memoryview获取缓冲区信息(无需数据复制)

当然可以实现,而且有两种可靠的无复制方案,直接获取memoryview底层的缓冲区元数据(指针、形状、步长等):

方案1:利用pybind11的py::buffer接口(推荐)

pybind11的memoryview对象支持通过request()方法获取对应的py::buffer实例,进而拿到py::buffer_info——这是pybind11封装的缓冲区信息结构体,包含了你需要的所有字段,且全程无数据复制。

代码示例

#include <pybind11/pybind11.h>

namespace py = pybind11;

void handle_memoryview(py::memoryview mv) {
    // 从memoryview请求buffer对象
    py::buffer buf = mv.request();
    // 获取buffer_info结构体
    auto buf_info = buf.request();

    // 提取所需信息
    void* data_ptr = buf_info.ptr;
    int num_dims = buf_info.ndim;
    std::vector<ssize_t> shape = buf_info.shape;
    std::vector<ssize_t> strides = buf_info.strides;
    ssize_t elem_size = buf_info.itemsize;

    // 示例:输出信息
    py::print("数据指针:", data_ptr);
    py::print("维度数:", num_dims);
    py::print("形状:", shape);
    py::print("步长:", strides);
    py::print("元素字节大小:", elem_size);
}

PYBIND11_MODULE(my_module, m) {
    m.def("handle_memoryview", &handle_memoryview, "接收memoryview并提取缓冲区信息");
}

方案2:直接调用Python C API

如果需要更底层的控制,可以直接通过pybind11拿到memoryview对应的PyObject*,调用Python原生的PyMemoryView_GET_BUFFER宏来获取Py_buffer结构体,同样无需复制数据。注意使用后必须调用PyBuffer_Release释放资源,避免内存泄漏。

代码示例

#include <pybind11/pybind11.h>
#include <Python.h>

namespace py = pybind11;

void handle_memoryview_low_level(py::memoryview mv) {
    PyObject* mv_obj = mv.ptr();
    Py_buffer buffer;

    // 获取底层缓冲区
    if (PyMemoryView_GET_BUFFER(mv_obj, &buffer) != 0) {
        throw py::error_already_set();
    }

    // 提取信息
    void* data_ptr = buffer.buf;
    int num_dims = buffer.ndim;
    std::vector<ssize_t> shape(buffer.shape, buffer.shape + num_dims);
    std::vector<ssize_t> strides(buffer.strides, buffer.strides + num_dims);
    ssize_t elem_size = buffer.itemsize;

    // 示例输出
    py::print("\n底层API获取的信息:");
    py::print("数据指针:", data_ptr);
    py::print("维度数:", num_dims);
    py::print("形状:", shape);
    py::print("步长:", strides);
    py::print("元素字节大小:", elem_size);

    // 必须释放缓冲区
    PyBuffer_Release(&buffer);
}

PYBIND11_MODULE(my_module, m) {
    m.def("handle_memoryview_low_level", &handle_memoryview_low_level, "用底层API处理memoryview");
}

关键注意事项

  • 两种方案都不会复制数据,直接访问memoryview指向的底层内存区域。
  • 方案1更符合pybind11的封装风格,无需手动管理资源,推荐优先使用。
  • 如果memoryview是只读的,获取的指针也会是只读的,写入操作会触发错误,需根据Python端传入的memoryview权限处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:27:43