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
);
}
}
};