【问题标题】:Boost Python No to_python converter found for std::stringBoost Python没有为std :: string找到to_python转换器
【发布时间】:2011-06-08 06:08:02
【问题描述】:

所以,我正在尝试创建一个 to_python 转换器,它允许我从公开的函数返回一个 boost::optional ,如果设置了 optional 则将其视为 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 抛出以下异常“TypeError: No to_python (by-value) converter found for C++ type: std::string”。我知道 C++ 能够将字符串转换为 python,因为我公开的大多数函数都返回字符串。为什么 boost::python::to_python_value 不能识别它,我该如何利用它所具有的任何转换器?

已通过更改为以下内容进行修复(基于this article):

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

现在只做另一个版本,这样它更干净,效果更好。

【问题讨论】:

  • 请将您的解决方案移至答案并接受它。

标签: c++ boost-python


【解决方案1】:

好的,这里是基于原始 C++ sig 帖子但重写为使用高级 boost.python API 的整个往返可选转换器(对不起,奇怪的间距)。

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

【讨论】:

  • 这很好用,非常感谢!但是,必须缺少一些东西:我不能使用[...].def("shortest", &amp;automaton::shortest, (arg("num") = boost::none)) 来声明默认为None 的可选参数,我必须写[...].def("shortest", &amp;automaton::shortest, (arg("num") = boost::optional&lt;unsigned&gt;()))。您是否知道缺少对boost::none 的支持?
【解决方案2】:

上面的代码有几个错别字——这里是更正的版本:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-18
    • 2015-09-03
    • 1970-01-01
    • 2022-01-03
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多