Использование Boost Python со слабыми Ptrs? - PullRequest
1 голос
/ 26 октября 2009

Попытка установить зависимость в C ++ с помощью отношения родитель-потомок. Родитель содержит дочерний элемент, а дочерний элемент имеет слабый указатель на родительский элемент.

Я также хотел бы иметь возможность получить от родителя в Python. Однако, когда я делаю это, я получаю слабую ошибку указателя, соединяющую эти отношения родитель-потомок.

C ++ код:

#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 в shared_ptr, я получаю ошибку указателя free () в Python.

Есть ли способ обойти эту проблему или я должен отказаться от использования слабых указателей с Boost Python?

Ответы [ 2 ]

2 голосов
/ 01 ноября 2009

Я играл с кодом без Python.

Это воспроизвело проблему:

Parent* p(new Parent);
p->initialize();

Проблема в том, что ничто не держит объект shared_ptr. Это исправляет это:

boost::shared_ptr<Parent> p(new Parent);
p->initialize();

Boost.Python FAQ: «Когда shared_ptr конвертируется из Python, shared_ptr фактически управляет ссылкой на содержащий объект Python. Когда shared_ptr конвертируется обратно в Python, библиотека проверяет, является ли он одним из этих» Python диспетчеры объектов "и если да, просто возвращает исходный объект Python"

Родитель * должен как-то храниться в shared_ptr. Я еще не понял, как.

Parent* parent = boost::python::extract<Parent*>(instance);
1 голос
/ 09 августа 2011

Интерфейс class_ позволяет вам контролировать, как объект удерживается. Это параметр шаблона, который называется HeldType. В документации Boost.Python содержится дополнительная информация о class_, но ваша привязка Python может выглядеть примерно так:

class_<Parent, boost::shared_ptr<Parent> >("Parent");
...