How to expose std::pair to python using boost::python?
Asked Answered
H

2

8

How to expose std::pair to python using boost::python? When I expose for example vector<string> I simply write:

class_<std::vector<std::string> >("StringVec")
    .def(vector_indexing_suite<std::vector<std::string> >())
;

But I don't know how to deal with std::pair.

Hemisphere answered 11/5, 2013 at 14:4 Comment(0)
H
12

I found a solution. The most simple example of exposing std::pair is:

class_<std::pair<int, int> >("IntPair")
    .def_readwrite("first", &std::pair<int, int>::first)
    .def_readwrite("second", &std::pair<int, int>::second);
Hemisphere answered 11/5, 2013 at 16:3 Comment(1)
However, this just creates a new Python class "IntPair" and does not reuse any existing Python features. It would be great to expose it as a Python tuple instead.Indiscreet
I
8

I'm using the following code to expose std::pair<> as Python tuples:

#include <boost/python.hpp>
namespace py = boost::python

template<typename T1, typename T2>
struct PairToPythonConverter {
    static PyObject* convert(const std::pair<T1, T2>& pair)
    {
        return py::incref(py::make_tuple(pair.first, pair.second).ptr());
    }
};

template<typename T1, typename T2>
struct PythonToPairConverter {
    PythonToPairConverter()
    {
        py::converter::registry::push_back(&convertible, &construct, py::type_id<std::pair<T1, T2> >());
    }
    static void* convertible(PyObject* obj)
    {
        if (!PyTuple_CheckExact(obj)) return 0;
        if (PyTuple_Size(obj) != 2) return 0;
        return obj;
    }
    static void construct(PyObject* obj, py::converter::rvalue_from_python_stage1_data* data)
    {
        py::tuple tuple(py::borrowed(obj));
        void* storage = ((py::converter::rvalue_from_python_storage<std::pair<T1, T2> >*) data)->storage.bytes;
        new (storage) std::pair<T1, T2>(py::extract<T1>(tuple[0]), py::extract<T2>(tuple[1]));
        data->convertible = storage;
    }
};

template<typename T1, typename T2>
struct py_pair {
    py::to_python_converter<std::pair<T1, T2>, PairToPythonConverter<T1, T2> > toPy;
    PythonToPairConverter<T1, T2> fromPy;
};

Within my main BOOST_PYTHON_MODULE(), I can then just use e.g. py_pair<int, int>(); to expose a pair of integers.

Indiscreet answered 11/1, 2017 at 14:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.