Reputation: 941
My goal is to be able to pass a std::map<double, double> from Python to C++, populate it in C++ and then see the results on the Python side. How is this achieved? I can't even get a std::vector to work.
I have a function definition in C++ like this
void predict(std::vector<T>& seq, std::map<T, double>& probabilities)
main.cpp looks like this
#include "node.h"
#include "probtree.h"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
PYBIND11_MAKE_OPAQUE(std::vector<double>);
PYBIND11_MAKE_OPAQUE(std::map<double, double>);
namespace py = pybind11;
using namespace std;
int main(int argc, char** argv){
}
PYBIND11_MODULE(sps_c, m){
py::bind_vector<std::vector<double>>(m, "VectorD");
py::bind_map<std::map<double, double>>(m, "MapDD");
py::class_<ProbTree<double>>(m, "ProbTree")
.def(py::init())
.def("process", &ProbTree<double>::process)
.def("predict", &ProbTree<double>::predict)
;
}
Nothing I expect to work works:
>>> import sps_c
>>> pt = sps_c.ProbTree
>>> vd = sps_c.VectorD
>>> m = sps_c.MapDD
>>> pt.process(vd)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: process(): incompatible function arguments. The following argument types are supported:
1. (self: sps_c.ProbTree, arg0: sps_c.VectorD) -> None
Invoked with: <class 'sps_c.VectorD'>
Maybe a List?
>>> pt.process([1.0])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: process(): incompatible function arguments. The following argument types are supported:
1. (self: sps_c.ProbTree, arg0: sps_c.VectorD) -> None
Invoked with: [1.0]
How do I make that work?
There is also an issue with STL methods not being available:
vd.push_back(1.0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'sps_c.VectorD' has no attribute 'push_back'
Do I have to write a bunch of boilerplate to get STL containers to work?
Upvotes: 1
Views: 1050
Reputation: 6004
Your first example doesn't work because you're calling a method with a class and not with an instance. This should work, I think:
>>> pt = sps_c.ProbTree()
>>> vd = sps_c.VectorD()
>>> pt.process(vd)
Regarding your second example: There's no automatic type conversion, so you'll need to convert yourself:
>>> pt_instance.process(sps_c.VectorD(vd))
About the third example: push_back
and other methods are available under their common Python names. This is not well documented, so here's a list of them (from here):
bind_vector
exposes append
, clear
, extend
, insert
, pop
, and some iterator methods.
bind_map
exposes keys
, values
, items
, and some iterator methods.
Those methods might not be available if the contained types are not copyable.
Upvotes: 2