Disclaimer: yes, I do know about boost::python::map_indexing_suite
.
Task: I have a C++ class which I want to wrap with Boost.Python. Its constructor takes a std::map
argument. Here is the C++ header:
// myclass.hh
typedef std::map<int, float> mymap_t;
class MyClass {
public:
explicit MyClass(const mymap_t& m);
// ...
};
// ...
Here is the Boost.Python wrapper (essential parts only):
// myclasswrapper.cc
#include "mymap.hh"
#include "boost/python.hpp"
#include "boost/python/suite/indexing/map_indexing_suite.hpp"
namespace bpy = boost::python;
// wrapping mymap_t
bpy::class_<mymap_t>("MyMap")
.def(bpy::map_indexing_suite<mymap_t>())
;
// wrapping MyClass
bpy::class_<MyClass>("MyClass", "My example class",
bpy::init<mymap_t>() // ??? what to put here?
)
// .def(...method wrappers...)
;
This compiles. However, I cannot create the mapped MyClass
object from the Python side because I don't know what to pass as argument to the constructor. Dictionaries do not get converted to std::map
-s automatically:
# python test
myclass = MyClass({1:3.14, 5:42.03})
the interpreter complains (rightly so):
Boost.Python.ArgumentError: Python argument types in
MyClass.__init__(MyClass, dict)
did not match C++ signature:
__init__(_object*, std::__1::map<int, float, ...
and MyMap
on the Python side cannot be initialised with a dictionary either.
Having googled away the best part of a day, I could find only examples for "normal" methods taking std::map
arguments that are mapped with .def(...)
. And in .def(...)
you do not have to specify explicitly the arguments of the mapped method, they are magically discovered. With constructors you must use boost::python::init<...>()
, or at least that is what I understood from the docs.
Questions:
- Shall I add something to the
MyMap
wrapper to helpmap_indexing_suite
convert from a Python dictionary? - Shall I use a different template argument in
boost::python::init<...>
in theMyClass
wrapper? - Any other ideas...?
Note: I have also seen this accepted answer at SO, then I scrolled down and read the comment by @YvesgereY:
"For the record, map_indexing_suite solution doesn't work, since no implicit "dict->std::map" from_python converter will be applied."
And I lost faith :-)