如何使用非平凡(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<Sequence>
和 seq
是一个 Sequence
,它包含两个向量,我想用作 numpy
数组的输入而不复制数据从 C++ 到 Python。
有谁知道pybind11或c++ python lib是否支持这个?
谢谢!
【问题讨论】:
【参考方案1】:我搞定了!我了解到,如果我想防止复制 feature
和 label
成员,而不是整个实际的 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.h
和 PYBIND11_MAKE_OPAQUE
来防止复制
【讨论】:
以上是关于如何使用非平凡(POD)类的缓冲区协议实现 pybind11的主要内容,如果未能解决你的问题,请参考以下文章
如何让 GCC 用非平凡的 const/dest 实例化一个类实例?
通过模板的特化实现 简单的类型萃取 实现memcppy时候对于特殊类型如string类的拷贝。