[C++-sig] Re: Containers for derived classes
Brett Calcott
brett.calcott at paradise.net.nz
Fri Aug 8 10:02:38 CEST 2003
>
> Sorry, it still doesn't work:
>
> class C {
> public:
> void set(A_ptr a) { this->a=a; }
> A_ptr get() { return this->a; }
> private:
> A_ptr a;
> };
>
> BOOST_PYTHON_MODULE(ptr_test)
> {
> using namespace boost::python;
> class_<A, A_ptr>("A", init< int >() )
> .def_readwrite("val", &A::val)
> ;
> class_<C>("C", init< >() )
> .def("set", &C::set )
> .def("get", &C::get )
> ;
> }
>
> Then, I get in Python:
> >>> from ptr_test import *
> >>> a=A(0)
> >>> c=C()
> >>> c.set(a)
> >>> a1=c.get()
> >>> a
> <ptr_test.A object at 0x008F76C0>
> >>> a1
> <ptr_test.A object at 0x008F68B0>
> >>> a.val
> 0
> >>> a1.val
> 0
> >>> a.val=1
> >>> a1.val
> 1
> >>>
> Hence, a and a1 are not the same Python objects, but the same C++ objects.
> Thus, sub-classing A still doesn't work:
>
> >>> class B(A):
> ... def __init__(self, i):
> ... A.__init__(self, i)
> ... self.name = "foo"
> ...
> >>> b=B(0)
> >>> c.set(b)
> >>> b1=c.get()
> >>> b
> <__main__.B object at 0x008F77B0>
> >>> b1
> <ptr_test.A object at 0x008F6F70>
> >>>
The problem is that for python object 'identity' the PyObject must survive
making it from the python interpreter to C++, and back again. In this case
it doesn't -- it is deleted when you set it, and a new one is constructed
when it returns.
Try this instead:
...
// class_<A, A_ptr>("A", init< int >() )
class_<A, boost::noncopyable>("A", init< int >() )
...
This does work. Why? Because Boost.Python uses shared_ptr<A> *internally* to
construct this object, and it does it in a special way so that the PyObject
is referenced as part of the shared_ptr<A> construct -- so it survives the
round trip.
Unfortunately, you can no longer do this (something I'd like to do in a
similar situation.)
class C {
public:
void set(A_ptr a) { this->a=a; }
A_ptr get() { return this->a; }
void create(int i) { a = A_ptr(new A(i)); }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
private:
A_ptr a;
};
>>>c.create(1)
>>>c.get()
TypeError: No to_python (by-value) converter found for C++ type: class
boost::s
ared_ptr<class A>
Because this particular shared_ptr is created in C++, it doesn't have the
funky embedded PyObject in it.
So, you get identity, but you lose consistent treatment of shared_ptr<A>. I
haven't figure a way to work around this...
HTH,
Brett
More information about the Cplusplus-sig
mailing list