简体   繁体   English

boost.python缓存包裹的类成员

[英]boost.python caching wrapped class members

I have a trivial classes dependency: 我有一个琐碎的类依赖:

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);
}

In Python 在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

Is there some way to create this APy wrapper once for an object? 是否有某种方法可以一次为对象创建此APy包装器? Especially, because inner object A is immutable(in this particular case). 特别是因为内部对象A是不可变的(在这种情况下)。 Otherwise, there is considerable overhead of creating lots of such temporary objects. 否则,创建大量此类临时对象会产生相当大的开销。

The APy wrappers are temporaries because s1, s2 are strings. APy包装器是临时的,因为s1, s2是字符串。 Once s1 is created, Python doesn't care if the setup that created it could also be used to create s2 . 创建s1 ,Python不会在乎创建它的设置是否也可以用于创建s2 Most likely ba gets discarded because it isn't stored. ba很可能因为未存储而被丢弃。 Does the same thing happen when you do something like 当您做类似的事情时也会发生同样的事情吗

a1 = b.a
s1 = a1.str1
s2 = a1.str1

?

Update: 更新:

We're trying to find out what ba actually is in Python. 我们正在尝试找出Python中的ba到底是什么。

Your invocation is 您的调用是

BOOST_PYTHON_IMPORT(wrapped) {

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

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

The definition of def_readwrite in boost/python/class.hpp is boost/python/class.hppdef_readwrite的定义是

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>()){...}

where the best matching implementation of def_readwrite_impl is def_readwrite_impl的最佳匹配实现是

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

because B::*a should be a member of B but not a function pointer. 因为B::*a应该是B的成员,而不是函数指针。 That in turn invokes 反过来调用

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

pm_ is an unbound pointer to some object of type B's a member. pm_是指向B类型某个对象的成员的未绑定指针。 Now, let's move on to add_property . 现在,让我们继续进行add_property

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

From here we go to boost/python/objects/class.hpp and look at class_base::add_property : 从这里我们转到boost / python / objects / class.hpp并查看class_base::add_property

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

Implementation is unfortunately hidden. 不幸的是,实施是隐藏的。 But the signature shows that the magic happens in make_getter . 但是签名表明魔术发生在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 is not doing anything to the pointer, because std::shared_ptr doesn't derive from boost::python::wrapper . unwrap_wrapper不会对指针做任何事情,因为std::shared_ptr并非源自boost::python::wrapper is_data_member_pointer was already part of the first macro. is_data_member_pointer已经是第一个宏的一部分。 I'm not sure if this is the broken part in your case because at some point digging for more decorators became really tedious. 我不确定这是否是您的坏处,因为在某个时候挖掘更多的装饰器真的很乏味。

Looking for some decorator definitions I stumbled upon bad news. 在寻找一些装饰器定义时,我偶然发现了一个坏消息。 Added it as a comment to your original question. 将其添加为对原始问题的评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM