对于以下两个类:
class A {
};
class B {
public:
B()
: a_(std::make_shared<A>())
{}
std::shared_ptr<A> a_;
};
有一个简单的boost.python
包装
A& get_a(const B& b) {
return *b.a_; // intentionally, no check here; doesn't matter for the example
}
boost::python::class_<A, std::shared_ptr<A>>("A");
boost::python::class_<B>("B")
.def("get_a", &get_a, boost::python::return_internal_reference<>());
在Python中有简单的成员检索:
import ext
b = ext.B()
a1 = b.get_a()
a2 = b.get_a()
我期待的是
id(a1) == id(a2)
不适用于上述情况,这意味着创建了两个不同的PyObject
作为A
包装器。
为什么? return_internal_reference
策略是否阻止创建多个临时对象?
如果我从std::shared_ptr<A>
返回get_a
,则程序无法编译。
此问题与此one有相似之处。然而,在后一种情况下,存在可能无法跟踪的临时物体。另一方面,成员变量的包装器存储在python变量中。
答案 0 :(得分:1)
return_internal_reference
策略允许返回指针或对内部持有对象的引用,而无需Boost.Python复制引用。它并不意味着后续调用将返回相同的Python对象。
以下是使用return_internal_reference
时未复制C ++对象的示例demonstrating,并且多个离散Python对象可以嵌入对同一C ++对象的引用:
#include <boost/python.hpp>
#include <cstdint> // std::uintptr_t
struct spam
{
uintptr_t id() { return reinterpret_cast<uintptr_t>(this); }
};
struct egg {};
spam& get_spam(const egg&)
{
static spam instance;
return instance;
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<spam>("Spam")
.def("id", &spam::id)
;
python::class_<egg>("Egg")
.def("get_spam", get_spam, python::return_internal_reference<>())
;
}
交互式使用:
import example
egg = example.Egg()
spam1 = egg.get_spam()
spam2 = egg.get_spam()
assert(spam1.id() == spam2.id()) # reference same C++ object
assert(id(spam1) != id(spam2)) # non-identical Python objects