c++ boost-python

c++ - Boost Python No se ha encontrado el convertidor to_python para std:: string



boost-python (2)

Hay algunos errores tipográficos en el código anterior, aquí está la versión corregida:

#include <boost/noncopyable.hpp> #include <boost/optional.hpp> #include <boost/python.hpp> template<typename T> struct python_optional : private boost::noncopyable { struct conversion : public boost::python::converter::expected_from_python_type<T> { static PyObject* convert(boost::optional<T> const& value) { using namespace boost::python; return incref((value ? object(*value) : object()).ptr()); } }; static void* convertible(PyObject *obj) { using namespace boost::python; return obj == Py_None || extract<T>(obj).check() ? obj : NULL; } static void constructor( PyObject *obj, boost::python::converter::rvalue_from_python_stage1_data *data ) { using namespace boost::python; void *const storage = reinterpret_cast< converter::rvalue_from_python_storage<boost::optional<T> >* >(data)->storage.bytes; if(obj == Py_None) { new (storage) boost::optional<T>(); } else { new (storage) boost::optional<T>(extract<T>(obj)); } data->convertible = storage; } explicit python_optional() { using namespace boost::python; if(!extract<boost::optional<T> >(object()).check()) { to_python_converter<boost::optional<T>, conversion, true>(); converter::registry::push_back( &convertible, &constructor, type_id<boost::optional<T> >(), &conversion::get_pytype ); } } };

Por lo tanto, estoy tratando de crear un convertidor de to_python que me permita devolver un boost :: opcional de una función expuesta y tratarlo como T si el opcional está configurado y Ninguno si no. Basado en una publicación que encontré en C++Sig , escribí el siguiente código.

template<typename T> struct optional_ : private boost::noncopyable { struct conversion { static PyObject* convert(boost::optional<T> const& value) { if (value) { return boost::python::to_python_value<T>()(*value); } Py_INCREF(Py_None); return Py_None; } }; explicit optional_() { boost::python::to_python_converter<boost::optional<T>, conversion>(); } };

Por lo que puedo decir, funciona para convertir los opcionales, pero python lanza la siguiente excepción "TypeError: No se encontró un convertidor de to_python (por valor) para C ++ type: std :: string". Sé que C ++ puede convertir cadenas a Python ya que la mayoría de mis funciones expuestas devuelven cadenas. ¿Por qué no refuerza :: python :: to_python_value, y cómo puedo utilizar cualquier convertidor que tenga?

Se corrigió cambiando a lo siguiente (basado en este artículo ):

template<typename T> struct optional_ : private boost::noncopyable { struct conversion { static PyObject* convert(boost::optional<T> const& value) { using namespace boost::python; return incref((value ? object(*value) : object()).ptr()); } }; explicit optional_() { boost::python::to_python_converter<boost::optional<T>, conversion>(); } };

Ahora solo hay que hacer la otra versión para que esté más limpia y funcione mejor.


Ok, aquí está el convertidor completo desde y hacia el opcional, basado en la publicación original de C ++ sig pero reescrito para usar la API boost.python de alto nivel (perdón por el espaciado extraño).

template<typename T> struct optional_ : private boost::noncopyable { struct conversion : public boost::python::converter::expected_from_python_type<T> { static PyObject* convert(boost::optional<T> const& value) { using namespace boost::python; return incref((value ? object(*value) : object()).ptr()); } }; static void* convertible(PyObject *obj) { using namespace boost::python; return obj == Py_None || extract<T>(obj).check() ? obj : NULL; } static void constructor(PyObject *obj, boost::python::converter::rvalue_from_python_stage1_data *data) { using namespace boost::python; void *const storage = reinterpret_cast< converter::rvalue_from_python_storage<boost::optional<T> >* >(data)->storage.bytes; if(obj == Py_None) { new (storage) boost::optional<T>(); } else { new (storage) boost::optional<T>(extract<T>(obj)); } data->convertible = storage; } explicit optional_() { using namespace boost::python; if(!extract<boost::optional<T> >(object()).check()) { to_python_converter<boost::optional<T>, conversion, true>(); converter::registry::push_back( &convertible, &constructor, type_id<boost::optional<T> >(), &conversion::get_pytype ); } } };