[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