I've got a function with the signature:
function(std::vector<double> vector);
And I've exposed it, but it doesn't take in Python lists. I've looked through the other SO answers, and most involve changing the function to take in boost::python::lists, but I don't want to change the function. I imagine I can use the vector_indexing_suite to write a simple wrapper around this function, but I have many functions of this form and would rather not write a wrapper for every single one. Is there a way to automatically make a Python list->std::vector mapping occur?
There are a few solutions to accomplish this without having to modify the original functions.
To accomplish this with a small amount of boilerplate code and transparency to python, consider registering a custom
converter
. Boost.Python uses registered converters when going between C++ and Python types. Some converters are implicitly created when creating bindings, such as whenclass_
exports a type.The following complete example uses an
iterable_converter
type that allows for the registration of conversion functions from a python type supporting the python iterable protocol. The example enable conversions for:std::vector<double>
std::vector<std::vector<std::String> >
std::list<foo>
Interactive usage:
A few comments on this approach:
iterable_converter::convertible
function could be changed to only allowing python list, rather than allowing any type that supports the iterable protocol. However, the extension may become slightly unpythonic as a result.example
extension namespace.Alternative approaches include:
boost::python::list
for each function accepting astd::vector
. This approach causes the bindings to scale based on the amount of functions being exported, rather than the amount of types needing converted.Using the Boost.Python
vector_indexing_suite
. The*_indexing_suite
classes export a type that is adapted to match some semantics of Python list or dictionaries. Thus, the python code now has to know the exact container type to provide, resulting in a less-pythonic extension. For example, ifstd::vector<double>
is exported asVecDouble
, then the resulting Python usage would be:However, the following would not work because the exact types must match, as exporting the class only registers a conversion between
VecDouble
andstd::vector<double>
:While this approach scales to types rather than functions, it results in a less pythonic extension and bloats the
example
namespace with unnecessary types.