[C++-sig] Possible bug for return_internal_reference with shared_ptr

David Abrahams dave at boost-consulting.com
Fri Aug 5 17:51:32 CEST 2005


"Dr. Michael Knecht" <michael.knecht at nanotechsoftware.de> writes:

> Hallo,
>
> i am using internal reference with shared pointers to handle borrowed
> references. 

<shiver>

I *really* think you don't want to do that.

> Here the code:
>
> begin cpp--------------------
> #include <boost/shared_ptr.hpp>
> #include <boost/python.hpp>
>
> using namespace boost;
> using namespace python;
>
> class B {
> public:
>     B() : _a(0) {}
>     void set(const int & a) { _a = a; }
>     const int & get() const { return _a; }
> private:
>     int _a;
> };
>
> typedef shared_ptr<B> ptr_type;
>
> class A {
> public:
>     A() : _a(new B()) {}
>     void set(const ptr_type & a) { _a = a; }
>     const ptr_type & get1() const { return _a; }
>     const ptr_type & get2() const { return _a; }
> private:
>     ptr_type _a;
> };
>
> BOOST_PYTHON_MODULE(ptr_test)
> {
>     class_<A, shared_ptr<A> >("A")
>         .def("set", &A::set)
>         .def("get1", &A::get1,
> return_value_policy<copy_const_reference>())
>         .def("get2", &A::get2,  return_internal_reference<>())
>     ;
>     class_<B, shared_ptr<B> >("B")
>         .def("set", &B::set)
>         .def("get", &B::get,
> return_value_policy<copy_const_reference>())
>     ;   
> }
> end cpp ---------------------
>
> begin python ---------
> from ptr_test import *
>
> a = A()
>
> b1 = a.get1()
> print b1.get()
>
> b2 = a.get2()
> print b2.get()
> end python -------------------- 
>
> If I execute the python script I get the following error message:
>
> TypeError: No Python class registered for C++ class boost::shared_ptr<B>
>
> begin out --------------------
> 0
> Traceback (most recent call last):
>   File "test.py", line 8, in ?
>     b2 = a.get2()
> TypeError: No Python class registered for C++ class boost::shared_ptr<B>
> end out -----------------------
>
> So return_value_policy<copy_const_reference> is working 

As it should.

> and return_internal_reference<> not!
>
> Any ideas why boost/python can not handle this? I think to handle
> internal references is importend for containers and iterators.

Because return_internal_reference doesn't do what you think.  It
builds an instance of the Python class corresponding to the type
referenced, and holding a pointer to the thing referenced (a
shared_ptr in this case) and maintaining the lifetime of the first
argument in order to keep the thing pointed to alive.  You didn't (and
shouldn't) register a class corresponding to shared_ptr<B>; you just
used shared_ptr<B> to hold the value of a class corresponding to B.

It might be nice if Boost.Python would let you get away with no
return_value_policy in these cases, but I have some doubts about
allowing return_internal_reference for shared_ptr<T>.  It would be
wasteful at best because it isn't really important to keep the first
argument to the wrapped function alive at all; the shared_ptr is
enough to keep the B object it references alive.

HTH,
-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com




More information about the Cplusplus-sig mailing list