如何使用 buffer 协议为非平凡 (POD) 类实现 pybind11

thi*_*ldi 4 c++ pybind11

我刚刚了解到Python Buffer Protocol,我想利用它从原始数据创建 pythonnumpy数组。C++我可以直接使用 pybind11 或 c++ python lib,但没有其他绑定生成器=/

阅读pybind11 文档并对其进行实验,我们似乎可以轻松地从简单的 C++ 结构(例如,std::vector<int>struct具有普通旧数据类型,如intfloat等)生成带有缓冲区协议的 python 绑定。然而,向更复杂的结构添加缓冲协议是不可能的,或者没有很好的记录。对于我的用例,我将 pybind a std::vector<struct Sequence>Sequence定义如下:

struct Sequence {
    std::vector<float> feature;
    std::vector<int> label;
}
Run Code Online (Sandbox Code Playgroud)

一旦在 C++ 端实现了与缓冲区协议的 python 绑定,在 Python 端我可以做

for seq in vector_sequence:
   feature_data=numpy.array(seq.feature, copy=False)`
   label_data=numpy.array(seq.label, copy=False)`.
Run Code Online (Sandbox Code Playgroud)

在上面的循环中,vector_sequence是 C++ 的不透明绑定std::vector<Sequence>,并且seq是 a Sequence,它保存我想要用作numpy数组输入的两个向量,而无需将数据从 C++ 复制到 Python。

有谁知道 pybind11 或 c++ python lib 是否支持此功能?

谢谢!

thi*_*ldi 5

我成功了!Sequence我了解到,如果我想防止复制 和feature成员label,而不是Sequence整个实际的类,则不必为类实现协议缓冲区。例子:

PYBIND11_MAKE_OPAQUE(std::vector<Sequence>);

py::bind_vector<std::vector<int>>(m, "VectorInt", py::buffer_protocol());
py::bind_vector<std::vector<float>>(m, "VectorFloat", py::buffer_protocol());

py::class_<SequenceReader>(m, "SequenceReader").def("read_sequences", &SequenceReader::read_sequences, py::return_value_policy::take_ownership);
Run Code Online (Sandbox Code Playgroud)

重要的是要注意我正在使用pybind11/numpy.hPYBIND11_MAKE_OPAQUE防止复制