[C++-sig] Getting Python Object for C++ object
abeyer at uni-osnabrueck.de
abeyer at uni-osnabrueck.de
Tue Aug 12 18:11:30 CEST 2003
It is already a classical problem: I would like to find the python object
for a given C++ object from within the C++ object. However, there is no
way I gonna wrap the classes as shown in the corresponding Howto example.
Thus, I will have to use shared_ptr instead.
Eventually I would like to call peer-objects with 'self' as an argument
from within C++ as well as from python. (BTW the latter is quite simple.)
My first attempt was the following:
class A : public enable_shared_from_this<A> {
public:
virtual python::object get_self() {
shared_ptr<A> self = shared_from_this();
assert(self != 0);
return python::object(self.get());
}
virtual ~A() {};
};
Certainly this only works after a shared pointer has
actually been created, e.g. by adding 'a' to another object
which only accepts shared_ptr<A>. Like:
typedef shared_ptr<A> A_ptr;
class C {
public:
void set(A_ptr a) {this->a = a;}
A_ptr get() { return this->a; };
private:
A_ptr a;
};
This will create a shared_ptr for an instance of 'A' if it gets
added to 'C' with set().
After that, shared_from_this() actually returns
a valid shared_ptr. However, that pointer apparently points
to another (new?) shared_ptr, because the python::object returned is
a new one. (Who can explain why shared_from_this() doesn't return the
shared_ptr created by boost:python?)
Here are the details:
BOOST_PYTHON_MODULE(self_test)
{
using namespace boost::python;
class_<A>("A" )
.def("get_self", &A::get_self)
;
class_<C>("C" )
.def("set", &C::set )
.def("get", &C::get )
;
}
>>> from self_test import *
>>> a=A()
>>> a.get_self()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
RuntimeError: boost::bad_weak_ptr
>>> c=C()
>>> c.set(a)
>>> a
<self_test.A object at 0x008F7750>
>>> c.get() # works
<self_test.A object at 0x008F7750>
>>> a.get_self() # returns new object
<self_test.A object at 0x008FB1E0>
>>>
Ok, this didn't work. However, 'C' seems to have the right shared_ptr of
'A'. So my work-around is that instances of A ask 'c' for their
shared_ptr. However, that is quit a hack:
class A {
A() : c(NULL) {};
python::object get_self() {
assert(c);
return python::object(c->get());
}
C *c;
};
void C::set(A_ptr a) {
this->a=a; // store instance
a->c = this; // register at 'a'
}
>>> from self_test import *
>>> a=A()
>>> c=C()
>>> c.set(a)
>>> a
<self_test.A object at 0x008F7750>
>>> c.get()
<self_test.A object at 0x008F7750>
>>> a.get_self()
<self_test.A object at 0x008F7750>
>>>
Has anyone a better idea?
Andreas
More information about the Cplusplus-sig
mailing list