boost::python: to-python conversion on polymorphic class

Hi, Is it possible to register to-python converters for polymorphic types held in shared_ptr? This does not seem to work for me. I have a virtual base class Object, and derived classes TypedAttribute<T> (with method 'value()' that returns a simple type - float, int etc). My boost.python registration code looks like so: template<typename Attrib> struct typed_attrib_topython { static PyObject* convert(const Attrib& a) { return bp::incref(bp::object(a.value()).ptr()); } }; template<typename T> struct TypedAttribBind { typedef TypedAttribute<T> attrib_t; TypedAttribBind() { boost::python::to_python_converter<attrib_t, typed_attrib_topython<attrib_t> >(); } }; However this doesn't work. I have other bound functions that return a boost::python::object(boost::shared_ptr<Object>), but these do not get converted. Am I misunderstanding to-python conversion? Should I expect this to work on polymorphic types? thanks in advance, Allan

At Fri, 10 Dec 2010 17:12:12 +1100, Allan Johns wrote:
Hi,
Is it possible to register to-python converters for polymorphic types held in shared_ptr? This does not seem to work for me.
I have a virtual base class Object, and derived classes TypedAttribute<T> (with method 'value()' that returns a simple type - float, int etc).
My boost.python registration code looks like so:
template<typename Attrib> struct typed_attrib_topython { static PyObject* convert(const Attrib& a) { return bp::incref(bp::object(a.value()).ptr()); } };
template<typename T> struct TypedAttribBind { typedef TypedAttribute<T> attrib_t;
TypedAttribBind() { boost::python::to_python_converter<attrib_t, typed_attrib_topython<attrib_t> >(); } };
However this doesn't work.
Doesn't work how? You shouldn't need to do anything special for shared_ptrs; just return them. Don't register converters. See shared_ptr.cpp in Boost.Python's libs/python/test/ directory. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Sorry I don't think I was being clear enough. I want to have the derived classes to-python convert into basic types (float ,string etc). In other words, I don't actually want TypedAttribute<T> to be directly bound at all. Background: I have a 'table' class that can hold various types of attributes (all derived from the same base class), a subset of which are just wrapper classes for POD types. I want these POD-based attributes to automatically to-python convert to the relevant types. I actually have this working at the moment but not by way of boost.python converters... I have a hand-rolled dispatcher going on (think std::map keyed on std::type_info), that my table class's python binding uses directly. But I'd rather not be duplicating boost.python functionality, if that's what I'm doing (it would seem more elegant, and more flexible, to do this with boost.python itself). Thanks! A On Sat, Dec 11, 2010 at 5:40 AM, Dave Abrahams <dave@boostpro.com> wrote:
At Fri, 10 Dec 2010 17:12:12 +1100, Allan Johns wrote:
Hi,
Is it possible to register to-python converters for polymorphic types
held
in shared_ptr? This does not seem to work for me.
I have a virtual base class Object, and derived classes TypedAttribute<T> (with method 'value()' that returns a simple type - float, int etc).
My boost.python registration code looks like so:
template<typename Attrib> struct typed_attrib_topython { static PyObject* convert(const Attrib& a) { return bp::incref(bp::object(a.value()).ptr()); } };
template<typename T> struct TypedAttribBind { typedef TypedAttribute<T> attrib_t;
TypedAttribBind() { boost::python::to_python_converter<attrib_t, typed_attrib_topython<attrib_t> >(); } };
However this doesn't work.
Doesn't work how?
You shouldn't need to do anything special for shared_ptrs; just return them. Don't register converters. See shared_ptr.cpp in Boost.Python's libs/python/test/ directory.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

At Mon, 13 Dec 2010 09:57:59 +1100, Allan Johns wrote:
Sorry I don't think I was being clear enough.
I want to have the derived classes to-python convert into basic types (float ,string etc). In other words, I don't actually want TypedAttribute<T> to be directly bound at all.
Oh, I see.
Background: I have a 'table' class that can hold various types of attributes (all derived from the same base class), a subset of which are just wrapper classes for POD types. I want these POD-based attributes to automatically to-python convert to the relevant types.
I actually have this working at the moment but not by way of boost.python converters... I have a hand-rolled dispatcher going on (think std::map keyed on std::type_info), that my table class's python binding uses directly. But I'd rather not be duplicating boost.python functionality, if that's what I'm doing (it would seem more elegant, and more flexible, to do this with boost.python itself).
You might start by answering the question of in which way what you did fails to work. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Right you are. With regards to my original snippet: template<typename Attrib> struct typed_attrib_topython { static PyObject* convert(const Attrib& a) { return bp::incref(bp::object(a.value()).ptr()); // return POD type } }; template<typename T> struct TypedAttribBind { typedef TypedAttribute<T> attrib_t; TypedAttribBind() { boost::python::to_python_converter<attrib_t, typed_attrib_topython<attrib_t> >(); } }; TypedAttribute<T> derives from Attribute, which derives from Object (the common polymorphic base class). TypedAttribute<T>.value() is a function which returns the POD type associated with the attribute. TypedAttribBind<T> is instantiated for a range of POD types T, in order to register the to-python converters. This doesn't behave as expected - if I call any bound function which returns a shared_ptr<Object> from python (where the object is actually a TypedAttribute<T>), I just get a wrapped Object back, rather than a POD type. On Mon, Dec 13, 2010 at 10:04 AM, Dave Abrahams <dave@boostpro.com> wrote:
At Mon, 13 Dec 2010 09:57:59 +1100, Allan Johns wrote:
Sorry I don't think I was being clear enough.
I want to have the derived classes to-python convert into basic types
(float
,string etc). In other words, I don't actually want TypedAttribute<T> to be directly bound at all.
Oh, I see.
Background: I have a 'table' class that can hold various types of attributes (all derived from the same base class), a subset of which are just wrapper classes for POD types. I want these POD-based attributes to automatically to-python convert to the relevant types.
I actually have this working at the moment but not by way of boost.python converters... I have a hand-rolled dispatcher going on (think std::map keyed on std::type_info), that my table class's python binding uses directly. But I'd rather not be duplicating boost.python functionality, if that's what I'm doing (it would seem more elegant, and more flexible, to do this with boost.python itself).
You might start by answering the question of in which way what you did fails to work.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

At Mon, 13 Dec 2010 10:56:25 +1100, Allan Johns wrote:
Right you are.
With regards to my original snippet:
template<typename Attrib> struct typed_attrib_topython { static PyObject* convert(const Attrib& a) { return bp::incref(bp::object(a.value()).ptr()); // return POD type } };
template<typename T> struct TypedAttribBind { typedef TypedAttribute<T> attrib_t;
TypedAttribBind() { boost::python::to_python_converter<attrib_t, typed_attrib_topython<attrib_t> >(); } };
TypedAttribute<T> derives from Attribute, which derives from Object (the common polymorphic base class). TypedAttribute<T>.value() is a function which returns the POD type associated with the attribute. TypedAttribBind<T> is instantiated for a range of POD types T, in order to register the to-python converters.
This doesn't behave as expected - if I call any bound function which returns a shared_ptr<Object> from python (where the object is actually a TypedAttribute<T>), I just get a wrapped Object back, rather than a POD type.
I *think* what you mean is that you don't get a Python built-in type (since POD is a C++ concept and you're looking at the resulting object from the Python side)? I'm afraid shared_ptr<T> is treated specially by Boost.Python at an extremely low level, so this is hard to do. However, although I can't support this usage, you might take a look in boost/python/converter/shared_ptr_to_python.hpp and consider creating an overload (in namespace boost::python::converter) for shared_ptr<Object>. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Thu, Dec 16, 2010 at 7:18 AM, Dave Abrahams <dave@boostpro.com> wrote:
At Mon, 13 Dec 2010 10:56:25 +1100, Allan Johns wrote:
Right you are.
With regards to my original snippet:
template<typename Attrib> struct typed_attrib_topython { static PyObject* convert(const Attrib& a) { return bp::incref(bp::object(a.value()).ptr()); // return
POD
type } };
template<typename T> struct TypedAttribBind { typedef TypedAttribute<T> attrib_t;
TypedAttribBind() { boost::python::to_python_converter<attrib_t, typed_attrib_topython<attrib_t> >(); } };
TypedAttribute<T> derives from Attribute, which derives from Object (the common polymorphic base class). TypedAttribute<T>.value() is a function which returns the POD type associated with the attribute. TypedAttribBind<T> is instantiated for a range of POD types T, in order to register the to-python converters.
This doesn't behave as expected - if I call any bound function which returns a shared_ptr<Object> from python (where the object is actually a TypedAttribute<T>), I just get a wrapped Object back, rather than a POD type.
I *think* what you mean is that you don't get a Python built-in type (since POD is a C++ concept and you're looking at the resulting object from the Python side)?
Yes sorry I was inferring built-in python types that are analogous to C++ POD types (float, int etc).
I'm afraid shared_ptr<T> is treated specially by Boost.Python at an extremely low level, so this is hard to do. However, although I can't support this usage, you might take a look in boost/python/converter/shared_ptr_to_python.hpp and consider creating an overload (in namespace boost::python::converter) for shared_ptr<Object>.
Ok thanks, I'll take a look at that. Cheers! A
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (2)
-
Allan Johns
-
Dave Abrahams