11.30.2015

C++/Python: Writing Custom Converters in Boost.Python

C++/Python: Boost.Python でカスタムコンバーターを作る

 

C++ のクラスを Python で扱うとき、std::pair などのクラスはデフォルトでは型変換が行われない。自分でコンバーターを書く必要がある。

 

以下はコードの例。C++11のラムダ式を利用したら綺麗にまとまった。

#include <boost/python.hpp>
#include "your_code.hpp"


namespace yourmodulename {
  namespace py = boost::python;

  /*
   * Converter for result set (std::vector of std::pair => pylist of pytuple)
   */
  namespace detail {
    template <typename T, typename U>
    struct pair_vector_to_tuple_list {
      static PyObject* convert(std::vector<std::pair<T, U> > const& ps) {
        py::list ret;
        for (auto it: ps) ret.append(py::make_tuple(it.first, it.second));
        return py::incref(ret.ptr());
      }

      static PyTypeObject const* get_pytype() { return &PyList_Type; }
    };
  }

  template <typename T, typename U>
  void expose_pair_vector_to_tuple_list() {
    py::to_python_converter<std::vector<std::pair<T, U> >, detail::pair_vector_to_tuple_list<T, U>, true>();
  }

  /*
   * Converter for list parameter (pylist => std::vector)
   */
  template <typename T>
  void expose_pylist_to_vector() {
    typedef std::vector<T> VT;

    auto convertible = [](PyObject* obj_ptr) -> void* { return PySequence_Check(obj_ptr) ? obj_ptr : NULL; };

    auto construct = [](PyObject* obj_ptr, py::converter::rvalue_from_python_stage1_data* data) {
      VT* storage = new (reinterpret_cast<py::converter::rvalue_from_python_storage<VT>*>(data)->storage.bytes) VT();
      for (py::ssize_t i = 0, l = PySequence_Size(obj_ptr); i < l; ++i) {
        storage->push_back(py::extract<typename boost::range_value<VT>::type>(PySequence_GetItem(obj_ptr, i)));
      }
      data->convertible = storage;
    };

    py::converter::registry::push_back(convertible, construct, py::type_id<VT>());
  }

}


BOOST_PYTHON_MODULE(yourmodulename) {
  using namespace boost::python;
  using namespace yourmodulename;

  // expose converters
  expose_pair_vector_to_tuple_list<int, double>();
  expose_pylist_to_vector<int>();

  // expose classes
  ...
}

なかなかに魔力を吸い取られそうなコードだ。

 

 

Related Posts

 

References

0 件のコメント:

コメントを投稿