[C++-sig] Problems with custom smart pointers and multiple inheritance

Chris Christophe.Gratin at adcis.net
Tue Mar 21 17:54:30 CET 2006


I am trying to interface some of our classes, multiply inheriting from 
abstract classes, and for which we use our own smart pointer template. 
So far I've managed to write the code listed below, but I am facing the 
following problems:

* my class member functions receive their parameter through smart 
pointers to base classes and not through standard C++ references, but 
only the PassARef(..) function call succeeds. PassAPointer causes the 
following runtime error:

     print c1.PassAPointer(c1)   # fails
Boost.Python.ArgumentError: Python argument types in 
MyBaseA.PassAPointer(MyClass, MyClass) did not match C++ signature:
     PassAPointer(class MyNamespace::MyBaseA {lvalue}, class 
MyNamespace::MyPointer<class MyNamespace::MyBaseA>)

* I need to know the PyObject wrapping my C++ class instance, but the 
"class syntax #2" invoking the constructor taking a PyObject as 
parameter works even worse.

* The Python object returned by 'GetBaseA()' is not the same as the 
calling Python object although they are actually referencing the same 
C++ class instance. Is there any way to avoid this ? (this is not the 
biggest of my problems though)


Chris.

-------
namespace MyNamespace
{
   class MyBaseA
   {
   public:
     virtual std::string PassARef(MyBaseA& value) = 0;
     virtual std::string PassAPointer(MyPointer<MyBaseA> value) = 0;
     virtual MyPointer<MyBaseA> GetBaseA() = 0;
   };

   class MyBaseB
   {
   public:
     virtual std::string PassBRef(MyBaseB& value) = 0;
   };

   class MyClass:
     public MyBaseA,
     public MyBaseB
   {
   private:
     PyObject* m_pyObject;

   public:
     std::string PassARef(MyBaseA& value)
     {
       return (boost::format("PassARef - %1%") % int(this)).str();
     }

     std::string PassAPointer(MyPointer<MyBaseA> value)
     {
       return (boost::format("PassAPointer - %1%") % int(this)).str();
     }

     MyPointer<MyBaseA> GetBaseA()
     {
       return MyPointer<MyBaseA>(this);
     }

     std::string PassBRef(MyBaseB& value)
     {
       return (boost::format("PassBRef - %1%") % int(this)).str();
     }

     MyClass()
     {
     }

     MyClass(PyObject* pyObject): m_pyObject(pyObject)
     {
     }

     static MyPointer<MyClass> New()
     {
       // No way to know the 'PyObject' is this case
       return MyPointer<MyClass>(new MyClass());
     }
   };
}

namespace boost { namespace python
{
   template <class T> struct pointee<MyNamespace::MyPointer<T> >
   {
     typedef T type;
   };

   template<class T> inline T * get_pointer(MyNamespace::MyPointer<T> 
const & p)
   {
     return p.get();
   }
}}

using namespace MyNamespace;

BOOST_PYTHON_MODULE(MyModule)
{
   class_<MyBaseA, boost::noncopyable>("MyBaseA", no_init)
     .def("PassARef", &MyBaseA::PassARef)
     .def("PassAPointer", &MyBaseA::PassAPointer)
     .def("GetBaseA", &MyBaseA::GetBaseA)
   ;

   class_<MyBaseB, boost::noncopyable>("MyBaseB", no_init)
     .def("PassBRef", &MyBaseB::PassBRef)
   ;

   // class_ syntax #1
   class_<MyClass, /*MyClass,*/ boost::noncopyable, bases<MyBaseA, 
MyBaseB> >("MyClass", no_init)
     .def("__init__", make_constructor(MyClass::New))
   ;

   // class_ syntax #2
   //class_<MyClass, MyClass, boost::noncopyable, bases<MyBaseA, 
MyBaseB> >("MyClass", init<>())
   //;

   register_ptr_to_python<MyPointer<MyClass> >();
   register_ptr_to_python<MyPointer<MyBaseA> >();
   register_ptr_to_python<MyPointer<MyBaseB> >();
}



# Python test code

   c1 = MyModule.MyClass()
   print c1
   print c1.PassARef(c1)
   print c1.PassAPointer(c1)  # fails
   print c1.PassBRef(c1)
   c2 = c1.GetBaseA()
   print c2                   # c2 is not the same Python object as c1
   print c2.PassARef(c1)      # but they point to the same C++ instance




More information about the Cplusplus-sig mailing list