[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