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);
}
在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是不可变的(在这种情况下). 否则,创建大量此类临时对象会产生相当大的开销.
Is there some way to create this APy wrapper once for an object? Especially, because inner object A is immutable(in this particular case). Otherwise, there is considerable overhead of creating lots of such temporary objects.
推荐答案
APy
包装器是临时的,因为s1, s2
是字符串.创建s1
后,Python不会在乎创建它的设置是否也可以用于创建s2
. b.a
很可能因为未存储而被丢弃.
当您做类似的事情时,会发生同样的事情吗
The APy
wrappers are temporaries because s1, s2
are strings. Once s1
is created, Python doesn't care if the setup that created it could also be used to create s2
. Most likely b.a
gets discarded because it isn't stored.
Does the same thing happen when you do something like
a1 = b.a
s1 = a1.str1
s2 = a1.str1
?
更新:
我们正在尝试找出Python中的b.a实际上是什么.
We're trying to find out what b.a actually is in 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);
}
boost/python/class.hpp
中def_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>()){...}
def_readwrite_impl
的最佳匹配实现是
class_<B>& def_readwrite_impl(char const* name, A B::*a,
char const* doc, mpl::true_)
因为B::*a
应该是B的成员,而不是函数指针.依次调用
because B::*a
should be a member of B but not a function pointer. That in turn invokes
class_<B>& def_readwrite_impl(char const* name, A B::*pm_, char const* doc, mpl::true_)
pm_
是指向B类型某个对象的成员的未绑定指针.
现在,让我们进入add_property
.
pm_
is an unbound pointer to some object of type B's a member.
Now, let's move on to 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
:
From here we go to boost/python/objects/class.hpp and look at class_base::add_property
:
void add_property(char const* name,
object const& fget, object const& fset, char const* docstr);
不幸的是,执行隐藏了起来.但是签名表明魔术发生在make_getter
中.
Implementation is unfortunately hidden. But the signature shows that the magic happens in 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::wrapper
派生的.
is_data_member_pointer
已经是第一个宏的一部分.我不确定这是否是您的坏处,因为在某个时候挖掘更多的装饰器真的很乏味.
unwrap_wrapper
is not doing anything to the pointer, because std::shared_ptr
doesn't derive from boost::python::wrapper
.
is_data_member_pointer
was already part of the first macro. 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.
这篇关于boost.python缓存包裹的类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!