Boost Python Не найден конвертер to_python для std :: string - PullRequest
17 голосов
/ 08 июня 2011

Итак, я пытаюсь создать конвертер to_python, который позволит мне возвращать boost :: опциональный из открытой функции и рассматривать его как T, если опциональный установлен, и None, если нет.Основываясь на сообщении, которое я нашел на C ++ Sig , я написал следующий код:

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

Насколько я могу судить, он работает для преобразования опций, но бросает Pythonследующее исключение «Ошибка типа: не найден конвертер to_python (по значению) для типа C ++: std :: string».Я знаю, что C ++ способен конвертировать строки в python, так как большинство моих открытых функций возвращают строки.Почему boost :: python :: to_python_value не распознает его, и как я могу использовать любой конвертер, который у него есть?

Исправлено путем изменения следующего (на основе этой статьи ):

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

Теперь просто сделайте другую версию, чтобы она была чище и работала лучше.

Ответы [ 2 ]

4 голосов
/ 22 июля 2011

Хорошо, вот полный конвертер в и из опционального конвертера, основанный на оригинальной записи сигнатуры C ++, но переписанный для использования API-интерфейса boost.python высокого уровня (извините за странный интервал).

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
      );
    }
  }
};
0 голосов
/ 19 февраля 2015

В приведенном выше коде есть несколько опечаток - вот исправленная версия:

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