如何使用非平凡 (POD) 的缓冲协议实现 pybind11 class

How to implement pybind11 with buffer protocol for non trivial (POD) class

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

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

struct Sequence {
    std::vector<float> feature;
    std::vector<int> label;
}

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

for seq in vector_sequence:
   feature_data=numpy.array(seq.feature, copy=False)`
   label_data=numpy.array(seq.label, copy=False)`.

在上面的循环中,vector_sequence 是 C++ std::vector<Sequence> 的不透明绑定,seq 是一个 Sequence,它包含我要使用的两个向量作为 numpy 数组的输入,无需将数据从 C++ 复制到 Python.

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

谢谢!

我成功了!我了解到,如果我想防止复制 featurelabel 成员,而不是实际的 Sequence,我不必为 Sequence class 实现协议缓冲区] class整体。 示例:

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);

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