在Boost Python中使用弱指针?

1 投票
2 回答
954 浏览
提问于 2025-04-15 15:23

我在尝试在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

如果我尝试把提取出来的父类指针转换成shared_ptr(共享指针),在Python中会出现一个free()无效指针的错误。

有没有办法解决这个问题,还是我应该放弃在Boost Python中使用弱引用?

2 个回答

1

class_这个接口让你可以控制对象是如何被保存的。它有一个叫做HeldType的模板参数。如果你想了解更多,可以去Boost.Python的文档查看class_的相关信息,但你的Python绑定可能看起来更像这样:

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

我在没有用到python的情况下玩了一些代码。

这样就能重现问题:

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

问题在于没有任何东西在持有这个shared_ptr对象。

这样可以解决这个问题:

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

Boost.Python常见问题解答:“当一个shared_ptr从Python转换过来时,shared_ptr实际上管理着对包含的Python对象的引用。当shared_ptr再转换回Python时,库会检查它是否是那些‘Python对象管理器’之一,如果是的话,就直接返回原来的Python对象。”

Parent*需要以某种方式存储在shared_ptr中。我还没有弄明白该怎么做。

Parent* parent = boost::python::extract<Parent*>(instance);

撰写回答