[C++-sig] Boost.Python, shared_ptr and *other* smart pointers

Andrea mariofutire at googlemail.com
Thu Jan 17 21:31:51 CET 2008


Hi,

I've already posted yesterday this message answering a very old message, but
It does not appear in the archive, so I post it again.

I'm trying to use my own smart pointer, but I cannot reproduce the behavior of boost::shared_ptr.
This is an other post about the same problem

http://mail.python.org/pipermail/c++-sig/2007-April/012241.html

I've been able to track down the issue to that: givem

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

It seems that Boost.Python is always able to call

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

passing 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, but 
it still understands it.
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...?

Could anybody help me?

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