Класс с dynamic_attr () не может передать __dict__ во внешнюю область - PullRequest
0 голосов
/ 18 октября 2019

Воспроизводимый пример кода

Мой код на С ++ очень прост:

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)

, то все в порядке.

У меня есть класс A с dynamic_attr, а класс B с dynamic_attr и Aобъект. Но я не могу передать динамическую особенность А. Б.

1 Ответ

0 голосов
/ 24 октября 2019

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'

Если у вас много объектов типа «А», второй подход будет более эффективным.

...