[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