具有dynamic_attr()的类无法将__dict__传递给外部范围

时间:2019-10-18 03:32:55

标签: pybind11

可复制的示例代码

我的c ++代码非常简单:

struct A
{   
    A()
    {
        this->a = 0;
    }
    py::int_ a;
};

struct B
{   
    B() {}
    A sa;
};


PYBIND11_MODULE(libdemo_ext, m)
{
    py::class_<A>(m, "A", py::dynamic_attr())
        .def(py::init<>())
        .def_readwrite("a", &A::a);
    py::class_<B>(m, "B", py::dynamic_attr())
        .def(py::init<>())
        .def_readwrite("sa", &B::sa);
}

当我像这样在python中使用它时:

def func(b):
    sa = b.sa
    sa.pa = 'hello'

b = B()
func(b)
print(b.sa.pa)

结果是:

Traceback (most recent call last):
  File "demo.py", line 12, in <module>
    print(b.sa.pa)
AttributeError: 'libdemo_ext.A' object has no attribute 'pa'

但是如果我这样使用它:

def func(b):
    sa = b.sa
    sa.pa = 'hello'

b = B()
sa = b.sa
func(b)
print(b.sa.pa)

这没关系。

我有一个带有dynamic_attr的类和一个带有dynamic_attr的B类和一个对象。 但是我不能通过B来转换A的动态功能。

1 个答案:

答案 0 :(得分:0)

pybind11跟踪绑定的对象,如果类型和C ++地址匹配,则重新使用它们。这就是第二种情况起作用的原因。我不知道您要描述的确切用例,但是如果始终将属性添加到函数中,则可以通过将引用与'b'对象的生存期绑定来确保引用保持有效。示例:

def func(b):
    b._sa = b.sa
    b.sa.pa = 'hello'

或:

def func(b):
    sa = b.sa
    b.__dict__['sa'] = sa
    sa.pa = 'hello'

如果您有许多类型为“ A”的对象,则第二种方法将更有效。