【发布时间】:2022-06-15 18:32:07
【问题描述】:
我正在尝试使用 pybind11 从 C++ 对象返回一个 numpy 数组,其中该数组是从 C++ 类拥有的内存创建的。现在,我有缓冲区协议公开的类并返回一个 py::array:
auto raw_image_cls =
py::class_<RawImage>(m, "RawImage", py::buffer_protocol());
....
.def_buffer([](RawImage &img) -> py::buffer_info {
size_t buff_sz = 0;
return py::buffer_info(
img.ImageData(buff_sz), img.BytesPerPixel(),
GetFormatDescriptor(img.BytesPerPixel()), 2,
{img.Height(), img.Width()},
{img.Width() * img.BytesPerPixel(), img.BytesPerPixel()}
);
})
.def_property_readonly(
"img",
[](RawImage &img) -> py::array {
size_t buff_sz = 0;
// py::capsule buffer_handle([]() {});
py::capsule buffer_handle(img.ImageData(buff_sz),
[](void *p) { free(p); });
return py::array(
py::buffer_info(
img.ImageData(buff_sz), img.BytesPerPixel(),
GetFormatDescriptor(img.BytesPerPixel()), 2,
{img.Height(), img.Width()},
{img.Width() * img.BytesPerPixel(), img.BytesPerPixel()}),
buffer_handle);
},
py::return_value_policy::reference_internal)
.....
当我使用 numpy 并执行以下操作时:
a = RawImage(filename)
b = numpy.array(a, copy=False)
a = 0
b
一切都按预期进行,并且 b 将保留。如果我这样做:
a = RawImage(filename)
b = a.img
a = 0
b
我得到一个段错误,这是有道理的,因为 a 被破坏了,但是我如何返回一个 py::array 并使用 numpy.array(a, copy=False) 获得相同的行为 - 这不会崩溃?
我试过了:
return py::array(py::buffer_info(
img.ImageData(buff_sz), img.BytesPerPixel(),
GetFormatDescriptor(img.BytesPerPixel()), 2,
{img.Height(), img.Width()},
{img.Width() * img.BytesPerPixel(), img.BytesPerPixel()}));
没有缓冲区句柄,但这只会制作完整的副本,这确实会减慢速度。有没有办法告诉 py:array 我们基本上只想返回一个引用或指向我在 C++ 中的内存的对象(来自 img.ImageData(sz))来做与 numpy.array(a, copy =假)?
【问题讨论】: