Making python bindings more consistent when using blitz arrays and std::vector of blitz arrays
Created by: laurentes
Our current python bindings that relies on C++ methods/functions that take blitz arrays as arguments are quite heterogeneous. Ideally, we should follow this way:
Given a class:
class Myclass {
public:
void setW(const blitz::Array<double,1>& w) { m_w = w; }
const blitz::Array<double,1>& getW() { return m_w; }
private:
blitz::Array<double,1> m_w;
};
The python binding could be done as follows:
static void py_setW(bob::Myclass& m, bob::python::const_ndarray w) {
machine.setW(w.bz<double,1>());
}
class_<bob::Myclass, boost::shared_ptr<bob::Myclass> >("Myclass",
"This class implements ...", init<>())
.add_property("w", make_function(&bob::Myclass::getW, return_value_policy<copy_const_reference>()), &py_setW, "Paramaters for ...")
For the getter, this will make a copy of the array and cast it into a NumPy array. For the setter, this allows various type (NumPy array, Python list) to be supported, and exceptions are managed by the bz<>() method.
For std::vector of blitz::Array's, the following could be done: Given a class:
class Myclass {
public:
void setW(const std::vector<blitz::Array<double,1> >& w) { m_w = ... }
const std::vector<blitz::Array<double,1> >& getW() { return m_w; }
private:
std::vector<blitz::Array<double,1> > m_w;
};
The python binding could be done as follows:
static void py_setW(bob::Myclass& m, object w) {
stl_input_iterator<bob::python::const_ndarray> dbegin(w), dend;
std::vector<bob::python::const_ndarray> wdata(dbegin, dend);
std::vector<blitz::Array<double,1> > wb;
for(size_t i=0; i<wdata.size(); ++i)
wb.push_back(wdata[i].bz<double,1>());
machine.setW(wb);
}
static object py_getW(bob::Myclass& m) {
boost::python::list l;
const std::vector<double,1>& w = m.getW();
for(size_t i=0; i<w.size(); ++i)
l.append(w[i]);
return boost::python::tuple(l);
}
class_<bob::Myclass, boost::shared_ptr<bob::Myclass> >("Myclass",
"This class implements ...", init<>())
.add_property("w", &py_getW, &py_setW, "Paramaters for ...")
This way, the setter allows heterogeneous python type (NumPy array, python list) and the getters relies on the copy automagically done from blitz to NumPy.