[C++-sig] std::tr1::shared_ptr as boost::shared_ptr

Andrea mariofutire at googlemail.com
Wed Jan 16 22:23:07 CET 2008


Piotr Jaroszynski wrote:
> Hello,
> 
> I am exposing a C++ app, which makes heavy use of tr1::shared_ptr, which seems 
> to be exactly(?) the same as boost::shared_ptr. I have managed to make most 
> of the stuff work just as it would be boost::shared_ptr ( additionally adding 
> support for shared_ptr<const T> - thanks to [1] ):
> 	
> Btw. I have seen [2] already, but it doesn't seem to cover that.
> 
> [1] - 
> http://language-binding.net/pyplusplus/troubleshooting_guide/shared_ptr/shared_ptr.html
> [2] - 
> http://language-binding.net/pyplusplus/troubleshooting_guide/smart_ptrs/smart_ptrs.html
> 

Hi,

I've got the same problem.
Basically, given

class A { ... };
class B : public A { ... };

It seems that Boost.Python is always able to call

void foo(const boost::shared_ptr<B> & x);

with and argument of type

OTHER_SMART_PTR<A>

How is it possile? I would like to achieve the same with my own smart pointer.
I've tried with tr1::shared_ptr, my own smart pointer, the *exact* same code as boost::shared_ptr 
copied with a different name...
It looks like boost::shared_ptr is *much* more powerful than all other smart pointers that can be 
registered.

Here is the code. How you can see, I never tell Boost.Python anything about boost::shared_ptr.
Then you can run the following python code

 >>> import bo
 >>> b=bo.newB(10)
 >>> print bo.getI_OK(b)
30
 >>> print bo.getI_FAIL(b)
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
     bo.getI_FAIL(B)
did not match C++ signature:
     getI_FAIL(std::tr1::shared_ptr<B>)

It seems that Boost.Python can extract the object from my smart pointer, dynamic_cast it to the 
right type and create a boost::shared_pointer. Just how...?

=============================================================================================================
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <tr1/memory>

using namespace boost::python;

#define OTHER_PTR std::tr1::shared_ptr

// needed by Boost.Python
template<class T> T * get_pointer(OTHER_PTR<T> const & p)
{
   return p.get();
}

class A
{
public:
   A(int i) : myInt(i) {}
   virtual ~A() {}
   virtual int getI() const { return myInt * 2; }
protected:
   int myInt;
};

class B : public A
{
public:
   B(int i) : A(i) {}
   virtual int getI() const { return myInt * 3; }
};

// how is it possible that Boost.Python knows how to create a boost::shared_ptr<B>?
// basically it can convert a OTHER_PTR<A> (as returned by newB) to a boost::shared_ptr<B> needed here
int getI_OK(const boost::shared_ptr<B> & a)
{
   return a->getI();
}

// but it cannot do it here
int getI_FAIL(const OTHER_PTR<B> & a)
{
   return a->getI();
}

OTHER_PTR<A> newB(int i)
{
   return OTHER_PTR<A>(new B(i));
}

BOOST_PYTHON_MODULE(bo)
{
   def("newB",      newB);
   def("getI_OK",   getI_OK);
   def("getI_FAIL", getI_FAIL);

   class_<A>           ("A", no_init);
   class_<B, bases<A> >("B", no_init);

   register_ptr_to_python<OTHER_PTR<A> >();
}
============================================================================================================

Andrea




More information about the Cplusplus-sig mailing list