Boost Python回调返回auto_ptr删除对象

时间:2013-04-29 14:05:19

标签: c++ boost-python auto-ptr

我为第三方库创建了绑定对象的所有权,因此我尝试使用FAQ中记录的auto_ptr。

这是我已经包装过的两个课程的一个例子:

typedef std::auto_ptr<Panel> PanelAutoPtr;

class NewPanelCallback {
public:
    NewPanelCallback(object c) { callable = c; }
    PanelAutoPtr operator() (wxWindow* parent) {
        object result = callable(boost::ref(parent));
        return extract<PanelAutoPtr>(result);
    }
private:
    object callable;
};

void Factory_register_method(Factory* f,
                             const wxString& id,
                             boost::python::object callable)
{
    f->registerFactoryMethod(id, NewPanelCallback(callable));
}

class_<Factory, boost::noncopyable>("Factory", no_init)
    .def("get", &Factory::get, return_value_policy<reference_existing_object>());
    .def("register", &Factory_register_method);

class_<Panel, std::auto_ptr<Panel>, bases<wxWindow>, boost::noncopyable)
    ("Panel", init<wxWindow*, int, const wxString&>()>;

我的应用程序允许插件开发人员将Python函数注册为用于创建窗口小部件的工厂方法。一个例子:

class MyPanel(shell.Panel):
    def __init__(self, parent, id, name):
        super().__init__(parent, id, name)

def create_panel(parent):
    return MyPanel(parent, -1, "Test")

shell.Factory.get().register("some_panel", create_panel)

现在,我的问题是当我的程序调用NewPanelCallback仿函数(在C ++中)时,面板对象在调用操作符返回之前被删除!它就像提取函数调用一样不会从结果对象中获取指针的所有权。

void create_a_panel(wxFrame* frm, NewPanelCallback& cb) {
    PanelAutoPtr p = cb(frm);
    frm->Add(p.get());
    p.release();
}

任何提示?

解决方案

我最后通过不使用&#34; extract&#34;来解决这个问题。这是我的新NewPanelCallback():

class NewPanelItemCallback {
public:
    NewPanelItemCallback(object c) { callable = c; }
    PanelAutoPtr operator() (wxWindow* parent) {
        return call<Shell::PanelAutoPtr>(callable.ptr(), boost::ref(parent));
    }
private:
    object callable;
};

我不确定为什么会这样,而另一种方式则不然。对此有任何意见将不胜感激。

3 个答案:

答案 0 :(得分:0)

不要使用auto_ptr - 它是邪恶的并且已弃用。将其替换为unique_ptr或shared_ptr。具体来说,auto_ptr更加急于通过无意中将所有权转移到temps来删除其有效负载,因为它缺少r值复制并且移动了unique_ptr和shared_ptr现在具有的语义。

答案 1 :(得分:0)

我找到了解决方案。我编辑了这个问题以包含答案。

答案 2 :(得分:0)

Boost支持movable语义和unique_ptr since v.1.55 但在我的项目中,我使用了以前的版本并制作了这样简单的包装器:

class_<unique_ptr<HierarchyT>, noncopyable>(typpedName<LinksT>("hierarchy", false)
, "hierarchy holder")
    .def("__call__", &unique_ptr<HierarchyT>::get,
        return_internal_reference<>(),
        "get holding hierarchy")
    .def("reset", &unique_ptr<HierarchyT>::reset,
        "reset holding hierarhy")
    ;

创建unique_ptr<HierarchyT>并将其传递给通过引用接受它的函数。 Python代码:

hier = mc.shierarchy()
mc.clusterize(hier, nds)

其中C ++函数是float clusterize(unique_ptr<HierarchyT>& hier,...) 然后使用Python访问结果:output(hier(), nds)
保持简单: - )