[C++-sig] Re: Containers for derived classes

abeyer at uni-osnabrueck.de abeyer at uni-osnabrueck.de
Thu Aug 7 09:56:26 CEST 2003


> abeyer at uni-osnabrueck.de writes:
>
>>>> However, the FAQ says there are more elegant ways by using
>>>> boost::shared_ptr:
>>>> "When a shared_ptr<X> is converted back to Python, the library checks to
>>>> see if it's one of those "Python object managers" and if so just returns
>>>> the original Python object."
>>>>
>>>> I have played with it, but I had no luck so far.
>>>
>>>What did you do?  Please post some code which illustrates.
>>>
>>>> Has anyone an example using shared_ptr that fits my purpose?
>>>
>>>If you make C a container of shared_ptr<A>, it should just work.
>>
>> OK, this is what I have tried:
>>
>> --- begin ptr_test.cpp
>>
>> #include <boost/shared_ptr.hpp>
>> #include <boost/python.hpp>
>>
>> using namespace boost;
>>
>> class A {
>>      public:
>> 	A(int i) : val(i) { }
>> 	int val;
>> };
>> typedef shared_ptr<A> A_ptr;
>>
>> class C {
>>      public:
>> 	void set(A_ptr& a) { this->a=a; }
>              ^^^^^^
>
> This is your problem.  Use A_ptr const& or better yet, plain A_ptr.
>
> Using a non-const reference means that Boost.Python has to find an
> actual A_ptr object within the source Python object.
>
>> 	A_ptr& get() { return this->a; }
>
> Likewise, you'd be better off just returning by-value here.

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>
>>>






More information about the Cplusplus-sig mailing list