带有类成员的 pybind11 缓冲区协议



我正在尝试使用 pybind11 绑定如下所示的结构

struct myStruct {
int na;
int nb;
double* a;
double* b;
}

我不确定正确的方法。pybind11 文档中的示例演示如何将缓冲区协议语义附加到对象,而不是附加到类成员。

我无法更改myStruct的界面以包含std::vector,这也允许我使用通常的.def_readwrite()

我试过做这样的事情

py::class_<myStruct>(m, "myStruct")
.def_property("a",
[](myStruct &s) {return py::array<double>({s.na}, {sizeof(double), s.a};)},
[](myStruct &s, py::array_t<double> val) {std::copy((double*) val.request().ptr, (double*) val.request().ptr + s.na, s.a);)}
)

哪个编译,但在 python 中我没有看到底层数据中仍然存在更改

print(my_struct.a[0]) # prints 0.0
my_struct.a[0] = 123.0
print(my_struct.a[0]) # still prints 0.0

嘿,很可能不是最优雅的答案,但也许它为您提供了一个起点和临时解决方案。我认为您需要做的是使用共享指针。

根据 https://github.com/pybind/pybind11/issues/1150 有人问了类似的东西,但我无法将其适应您的示例,并且只得到了与您相同的结果,而没有更改数据。

在您的特定示例中,对我有用的是使用 shared_ptr 并为指针定义 setter 和 getter 函数,并为 pybin11 类提供简单的def_property。

class class_DATA{
public: 
int na;
std::shared_ptr<double> a;  
void set_a(double a){*class_DATA::a = a; };
double get_a(void){return *class_DATA::a; };
};
PYBIND11_MODULE(TEST,m){
m.doc() = "pybind11 example plugin";
//the costum class
py::class_<class_DATA>(m, "class_DATA", py::dynamic_attr())
.def(py::init<>())    //needed to define constructor
.def_readwrite("na", &class_DATA::na)
.def_property("a", &class_DATA::get_a, &class_DATA::set_a, py::return_value_policy::copy);
}

最新更新