Использование Boost Python со слабыми Ptrs?
-
06-07-2019 - |
Вопрос
Попытка установить зависимость в C++ с отношениями родитель-потомок.Родительский элемент содержит дочерний элемент, а дочерний элемент имеет слабый указатель на родителя.
Я также хотел бы иметь возможность производить производные от родителя в Python.Однако когда я это делаю, я получаю ошибку слабого указателя, связывающую отношения родитель-потомок.
Код С++:
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
using namespace boost;
using namespace boost::python;
struct Child;
struct Parent : public enable_shared_from_this<Parent>
{
void initialize();
shared_ptr<Child> m_child;
};
struct Child: public enable_shared_from_this<Child>
{
void setParent(shared_ptr<Parent> ptr);
weak_ptr<Parent> m_parent;
};
void Parent::initialize()
{
shared_ptr<Child> ptr(new Child);
m_child = ptr;
m_child->setParent(shared_from_this());
}
void Child::setParent(shared_ptr<Parent> ptr)
{
m_parent = ptr;
}
static PyObject* create(PyObject* object)
{
PyObject* instance = PyObject_CallObject(object, NULL);
Parent* parent = extract<Parent*>(instance);
parent->initialize();
return instance;
}
Привязка Python:
BOOST_PYTHON_MODULE(test_module)
{
class_<Parent>("Parent");
def("create", &create);
}
Код Python:
from test_module import *
class Test(Parent):
def __init__(self):
Parent.__init__(self)
n = create(Test)
Ошибка:
Traceback (most recent call last):
File "main.py", line 8, in <module>
n = create(Test)
RuntimeError: tr1::bad_weak_ptr
Если я попытаюсь преобразовать извлеченный указатель на Parent в общий_ptr, я получу ошибку недопустимого указателя free() в Python.
Есть ли способ обойти эту проблему или мне следует отказаться от использования слабых указателей с Boost Python?
Решение
Я играл с кодом без питона.
Это воспроизвело проблему:
Parent* p(new Parent);
p->initialize();
Проблема в том, что за объектомshared_ptr ничего не удерживается.Это исправляет это:
boost::shared_ptr<Parent> p(new Parent);
p->initialize();
Часто задаваемые вопросы по Boost.Python:«Когда общий_ptr преобразуется из Python, общий_ptr фактически управляет ссылкой на содержащий его объект Python.Когдаshared_ptr преобразуется обратно в Python, библиотека проверяет, является ли он одним из тех «менеджеров объектов Python», и если да, то просто возвращает исходный объект Python».
Родитель* необходимо каким-то образом сохранить в файлеshared_ptr.Я еще не придумал как.
Parent* parent = boost::python::extract<Parent*>(instance);
Другие советы
Интерфейс class_ позволяет вам контролировать способ удержания объекта.Это параметр шаблона, называемый HeldType.Дополнительную информацию можно найти в документации Boost.Python по class_, но ваша привязка Python может выглядеть примерно так:
class_<Parent, boost::shared_ptr<Parent> >("Parent");