[C++-sig] problems downcasting intrusive_ptr.

Lucio Moser lucio at image-engine.com
Sat Feb 10 01:45:05 CET 2007


Hello,

I created a factory function that returns an intrusive pointer for a 
derived class.
The returned pointer is for the base class, but boost.python apparently 
downcast it correctly.
I can call methods from the derived class with no problem.
But then, if I pass that object to any function that requires a derived 
pointer it will fail.

If I use shared_ptr instead. It works fine.

Any ideas?
Thank you!

PS: I'm using boost 1.33.1.

python test case:
============
Object b can't be given as a parameter for test2() function!!!

Python 2.5 (r25:51908, Nov 17 2006, 14:19:39)
[GCC 4.0.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
 >>> from simpleTest import *
 >>> a = Derived()
 >>> b = factory()
 >>> b
<simpleTest.Derived object at 0xb7e87d84>
 >>> a.test1()
0
 >>> b.test1()
0
 >>> a.test2(a)
1
 >>> b.test2(a)
1
 >>> b.test2(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    Derived.test2(Derived, Derived)
did not match C++ signature:
    test2(Derived {lvalue}, boost::intrusive_ptr<Derived>)
 >>> a.test2(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    Derived.test2(Derived, Derived)
did not match C++ signature:
    test2(Derived {lvalue}, boost::intrusive_ptr<Derived>)
 >>>

simpleTest.cpp:
===========

#include <boost/python.hpp>

class Base
{
    public :

        Base ( ) : m_numRefs( 0 )
        {
        }

        // Functions used for intrusive_ptr reference counting.

        /// Add a reference to the current object
        void addRef() const {
            m_numRefs ++;
        }
   
        /// Remove a reference from the current object
        void removeRef() const {
            m_numRefs --;
            if ( m_numRefs == 0 )
            {
                delete this;
            }
        }

    protected :
        mutable unsigned int m_numRefs;

        virtual ~Base()
        {
        }
};


class Derived;

#ifdef USE_SHARED_PTR

#include "boost/shared_ptr.hpp"
typedef boost::shared_ptr<Base> BasePtr;
typedef boost::shared_ptr<Derived> DerivedPtr;

#else    // USE_SHARED_PTR

#include "boost/intrusive_ptr.hpp"
typedef boost::intrusive_ptr<Base> BasePtr;
typedef boost::intrusive_ptr<Derived> DerivedPtr;

/// Functions required to allow use of Base with boost::intrusive_ptr
inline void intrusive_ptr_add_ref( const Base *r )
{
    r->addRef();
}

inline void intrusive_ptr_release( const Base *r )
{
    r->removeRef();
}
#endif    // USE_SHARED_PTR

class Derived : public Base
{
    public :
        Derived( ) : Base ( ), m_data( 0 )
        {
        }

        int test1()
        {
            return this->m_data;
        }

        int test2( DerivedPtr d )
        {
            return (this->m_data == d->m_data);
        }

    protected :
        int m_data;
};

BasePtr factory( void )
{
    return BasePtr( new Derived() );
}

using namespace boost::python;

BOOST_PYTHON_MODULE(simpleTest)
{
    class_< Base, boost::noncopyable, BasePtr > BaseClass("Base", no_init);

    class_< Derived, boost::noncopyable, DerivedPtr, bases< Base > > 
DerivedClass( "Derived" );
    DerivedClass.def( "test1", &Derived::test1 );
    DerivedClass.def( "test2", &Derived::test2 );

    def("factory", &factory);

    implicitly_convertible<DerivedPtr, BasePtr>();
}




More information about the Cplusplus-sig mailing list