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

Posted

技术标签:

【中文标题】如何使用非平凡(POD)类的缓冲区协议实现 pybind11【英文标题】:How to implement pybind11 with buffer protocol for non trivial (POD) class 【发布时间】:2019-05-10 22:01:10 【问题描述】:

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

阅读pybind11 docs 并对其进行试验,似乎我们可以轻松地从琐碎的C++ 结构(例如std::vector<int>struct 使用诸如int、@987654328 等普通旧数据类型的缓冲区协议生成python 绑定@, ETC)。但是,将缓冲区协议添加到更复杂的结构是不可能的或没有很好的文档记录。对于我的用例,我将绑定一个std::vector<struct Sequence>Sequence 的定义如下:

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

一旦在 C++ 端实现了带有缓冲区协议的 python 绑定,在 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&lt;Sequence&gt;seq 是一个 Sequence,它包含两个向量,我想用作 numpy 数组的输入而不复制数据从 C++ 到 Python。

有谁知道pybind11或c++ python lib是否支持这个?

谢谢!

【问题讨论】:

【参考方案1】:

我搞定了!我了解到,如果我想防止复制 featurelabel 成员,而不是整个实际的 Sequence 类,我不必为 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);

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

【讨论】:

以上是关于如何使用非平凡(POD)类的缓冲区协议实现 pybind11的主要内容,如果未能解决你的问题,请参考以下文章

php socket 如何实现非阻塞

如何让 GCC 用非平凡的 const/dest 实例化一个类实例?

通过模板的特化实现 简单的类型萃取 实现memcppy时候对于特殊类型如string类的拷贝。

如何将 std::variant 与非平凡的用户对象(稍后构建)一起使用,并让访问者使用自动 lambda?

非平凡Java数学练习

使用 requires 的可选非平凡析构函数