[C++-sig] Re: Pointer to existing Python object
David Abrahams
dave at boost-consulting.com
Thu Apr 28 23:09:21 CEST 2005
Andreas Beyer <beyer at imb-jena.de> writes:
> Hi:
>
> I know that there has been some discussion on this subject on c++ sig.
> However, I could not find a solution for my specific problem and maybe
> there is no solution.
>
> Here we go:
>
> I have a container class B that creates instances of class A - both
> in C++. In Python I can get instances of A from B with a get()
> method. I would like to get an existing Python object whenever such
> object existis and I would like to get a new Python object if no
> Python object for A exists.
This is hard to do. I see that you're using shared_ptr and that's a
good start. What you need to do, the moment a shared_ptr is about to
be released to Python, is replace it:
template <class T>
hold_python(shared_ptr<T>& x)
{
x = extract<shared_ptr<T> >( python::object(x) );
}
> An example:
>
>
> using namespace boost;
>
> class A : public enable_shared_from_this<A> {
> public:
> A() : val(0) {};
> int val;
> typedef shared_ptr<A> A_ptr;
> A_ptr self() {
> A_ptr self;
> self = shared_from_this();
> return self;
> }
>
> };
>
>
> class B {
> public:
> B() {
> a = A::A_ptr(new A());
> }
> A::A_ptr a;
> void set(A::A_ptr a) {
> this->a = a;
> }
>
> A::A_ptr get() {
> return a->self();
What was wrong with
return a;
here?
> }
> };
>
A::A_ptr get_b_a(B& b)
{
hold_python(b.a);
return b.a;
}
> BOOST_PYTHON_MODULE(ptr_test) {
> python::class_<A> ("A")
> .def_readwrite("val", &A::val)
> ;
> python::register_ptr_to_python< A::A_ptr >();
>
> python::class_<B>("B")
> .def("set", &B::set)
> .def("get", &B::get)
.def("get", get_b_a) // <=== here
> ;
> }
>
>
> In Python I would like to do this:
>
>>>> b = B()
>>>> a1 = b.get() # obtain instance of class A
>>>> a2 = b.get() # get the *same Python instance* again
>>>> assert(a1==a2)
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AssertionError
>>>>
>
> The internal representations of instances of A are the same! Whenever I
> access a C++ member of A I am actually accessing the same object. So I
> can do this:
>>>> a1.val = 42 # change internal reference
>>>> print a2.val
> 42
>>>>
> However, I cannot do this:
>>>> a1.foo = 42
>>>> print a2.foo
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: 'A' object has no attribute 'foo'
>>>>
>
> I think instances of B have to check if there is already an existing
> Python object. In that case B (or a wrapper of B) should return the
> existing Python object (i.e. instances of python::object). Is there a
> way to find such an existing instance?
HTH,
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Cplusplus-sig
mailing list