boost.python缓存包装类成员

时间:2016-08-08 10:26:49

标签: c++ boost boost-python

我有一个琐碎的类依赖:

class A {
    ... // constructor is omitted 
public:
    const std::string str1;
};
class B {
public:
    std::shared_ptr<A> a;
}

BOOST_PYTHON_IMPORT(wrapped) {

    class_<A, std::shared_ptr<A>>("APy")
    .def_readonly("str1", &A::str1);

    class_<B>("BPy")
    .def_readwrite("a", &B::a);
}

在Python中

import wrapped as wr
b = wr.BPy()
s1 = b.a.str1 // APy wrapper created
s2 = b.a.str1 // new APy wrapper created even though object is the same

有没有办法为对象创建一次这个APy包装器? 特别是,因为内部对象A是不可变的(在这种特定情况下)。 否则,创建大量此类临时对象会产生相当大的开销。

1 个答案:

答案 0 :(得分:0)

APy包装器是暂时的,因为s1, s2是字符串。创建s1后,如果创建它的设置也可用于创建s2,则Python并不在意。最有可能b.a被丢弃,因为它没有被存储。 当您执行类似

之类的操作时,会发生同样的事情
a1 = b.a
s1 = a1.str1
s2 = a1.str1

<强>更新

我们正试图找出什么是b.a实际上是在Python中。

您的调用是

BOOST_PYTHON_IMPORT(wrapped) {

    class_<A, std::shared_ptr<A>>("APy")
    .def_readonly("str1", &A::str1);

    class_<B>("BPy")
    .def_readwrite("a", &B::a);
}

def_readwriteboost/python/class.hpp的定义是

template <class D>
self& def_readwrite(char const* name, D const& d, char const* doc=0)
{
    return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
// translates to
class_<B>& def_readwrite(char const* name, A &d,
  char const* doc=0, detail::is_data_member_pointer<B>()){...}

def_readwrite_impl的最佳匹配实现是

class_<B>& def_readwrite_impl(char const* name, A B::*a,
  char const* doc, mpl::true_) 

因为B::*a应该是B的成员而不是函数指针。这反过来调用

class_<B>& def_readwrite_impl(char const* name, A B::*pm_, char const* doc, mpl::true_)

pm_是指向B类型成员的某个对象的未绑定指针。 现在,让我们转到add_property

class_<B>& add_property(char const* name, A &fget = B::*a,
  A &fset = B::*a, char const* docstr = 0)

从这里我们去boost / python / objects / class.hpp并查看class_base::add_property

void add_property(char const* name, 
    object const& fget, object const& fset, char const* docstr);

遗憾的是隐藏了实施。但签名表明神奇发生在make_getter

template <class F>
object make_getter(F f)
{
    typedef typename api::is_object_operators<F>::type is_obj_or_proxy;

    return this->make_fn_impl(
        detail::unwrap_wrapper((W*)0)
      , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
    );
}

unwrap_wrapper没有对指针做任何事情,因为std::shared_ptr并非来自boost::python::wrapperis_data_member_pointer已经是第一个宏的一部分了。我不确定这是否是你案件中的破碎部分,因为在某些时候挖掘更多装饰者变得非常繁琐。

寻找一些装饰者定义我偶然发现了坏消息。将其添加为对原始问题的评论。