2

我正在为获取对象所有权的第 3 方库创建绑定,因此我尝试使用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();
}

有什么提示吗?

解决方案

我终于通过不使用“提取”来解决这个问题。这是我的新 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;
};

我不太确定为什么这行得通,而另一种方式则行不通。对此的任何评论将不胜感激。

4

3 回答 3

0

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

于 2013-04-30T10:33:34.817 回答
0

Boost 支持movable语义,并且unique_ptr 从 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).
把事情简单化 :-)

于 2014-01-11T06:32:11.420 回答
0

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

于 2013-04-29T14:22:52.067 回答