[C++-sig] boost::python and custom smart pointer
Gabriel Becedillas
gabriel.becedillas at corest.com
Thu Mar 1 20:10:52 CET 2007
Hi,
I'd like to have my custom smart_ptr behave like boost::shared_ptr
regarding from_python conversions. To_python converstions work fine, but
the problem arises when I have an instance to a derived class via a
smart_ptr to the base class MySmartPtr<Base> and this has to be passed
to a function receiving MySmartPtr<Derived>. If I use boost::shared_ptr
this works just fine. I think I'm doing something wrong in
MySmartPtr_from_python.
I'm pasting a simplified version of my code:
------ BEGIN C++ CODE ------
// Dummy smart pointer class.
template <typename T>
class MySmartPtr
{
public:
MySmartPtr() :
m_P(NULL)
{
}
MySmartPtr(T* a_P) :
m_P(a_P)
{
}
T* m_P;
};
namespace boost {
namespace python {
template <typename T>
T* get_pointer(MySmartPtr<T> const& a_P)
{
return a_P.m_P;
}
template <typename T>
struct pointee< MySmartPtr<T> >
{
typedef T type;
};
} // namespace python
} // namespace boost
template <class T>
struct MySmartPtr_from_python
{
static void* convertible(PyObject* p)
{
if (p == Py_None)
return p;
return boost::python::converter::get_lvalue_from_python(p,
boost::python::converter::registered< MySmartPtr<T> >::converters);
}
static void construct(PyObject* source,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
void* const storage =
((boost::python::converter::rvalue_from_python_storage<MySmartPtr<T>
>*)data)->storage.bytes;
if (data->convertible == source) // This is because convertible
returned p if p was Py_None.
new (storage) MySmartPtr<T>();
else
new (storage) MySmartPtr<T>( *((MySmartPtr<T>*)data->convertible) );
data->convertible = storage;
}
};
class Base
{
public:
virtual ~Base()
{}
};
class Derived :
public Base
{
};
boost::shared_ptr<Base> build_ok()
{
return boost::shared_ptr<Base>(new Derived());
}
MySmartPtr<Base> build_fail()
{
return MySmartPtr<Base>(new Derived());
}
void test_ok(boost::shared_ptr<Derived> a_Derived)
{}
void test_fail(MySmartPtr<Derived> a_Derived)
{}
template <typename T>
void register_MySmartPtr_conversions()
{
boost::python::register_ptr_to_python< MySmartPtr<Base> >();
boost::python::converter::registry::insert(
&MySmartPtr_from_python<T>::convertible,
&MySmartPtr_from_python<T>::construct,
boost::python::type_id< MySmartPtr<T> >()
);
}
BOOST_PYTHON_MODULE(bptest)
{
boost::python::class_<Base, boost::noncopyable> class_Base("Base",
boost::python::no_init);
boost::python::register_ptr_to_python< boost::shared_ptr<Base> >();
register_MySmartPtr_conversions<Base>();
boost::python::class_<Derived, boost::noncopyable,
boost::python::bases<Base> > class_Derived("Derived",
boost::python::no_init);
boost::python::register_ptr_to_python< boost::shared_ptr<Derived> >();
register_MySmartPtr_conversions<Derived>();
boost::python::def("build_ok", build_ok);
boost::python::def("test_ok", test_ok);
boost::python::def("build_fail", build_fail);
boost::python::def("test_fail", test_fail);
}
------ END C++ CODE ------
This python code fails to work:
import bptest
bptest.test_ok(bptest.build_ok())
bptest.test_fail(bptest.build_fail())
And this is the error that I get:
Boost.Python.ArgumentError: Python argument types in
bptest.test_fail(Derived)
did not match C++ signature:
test_fail(class MySmartPtr<class Derived>)
Thanks in advance.
--
Gabriel Becedillas
Developer
CORE SECURITY TECHNOLOGIES
More information about the Cplusplus-sig
mailing list