Boost logo

Boost Users :

Subject: [Boost-users] boost::python wrapping a container of boost::variant?
From: Mario Lang (mlang_at_[hidden])
Date: 2014-02-05 09:33:19


Hi.

Does anyone have ideas how to convince boost::python to wrap
a container of boost::variant? I need this to generate
useful python bindings for a project of mine which uses boost::variant
internally. Since python supports heterogenous containers natively,
it seems to me this should be doable. However, I have attempted to find
a solution on my own on several occasions, and always failed.

One obvious hint is the indexing_suite. However, now that I looked at
it again, I think I know where the problem is: The get_item method of
indexing_suite always returns a data_type object, which is value_type
from the container in question. However, from what I can see, I'd need
something that converts to boost::python::object, so that I can return
whatever class is appropriate for the actual variant instance.
In other words, get_item would need to return a boost::python::object
instead of data_type.

To illustrate in code what I want, here is a minimal example:

#include <boost/python.hpp>
#include <boost/variant.hpp>

struct a {
  int x;
};

struct b {
  double y;
};

typedef boost::variant<a, b> variant;
typedef std::vector<variant> vector;

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

  class_<a>("a", init<a>())
    .def(init<>())
    .def_readonly("x", &a::x);
  class_<b>("b", init<b>())
    .def(init<>())
    .def_readonly("y", &b::y);
}

The question is, how do I expose std::vector<variant> to Python?

I guess I need to define a static_visitor that returns python objects,
something like:

struct to_python_visitor : boost::static_visitor<boost::python::object>
{
  result_type operator()(a const &a_) const {
    // return a boost::python::object that refers to a_
  }
  ...
};

And hook that up to the container support somehow such that

boost::apply_visitor(to_python_visitor(), variant_instance)

is called whenever a value is retrieved from the container.

Can this even be done with current Boost.Python?

Any hints, maybe even concrete code examples, would be highly
appreciated.

-- 
CYa,
  ⡍⠁⠗⠊⠕

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net