c++lambdaeigenpybind11

# Reference on Eigen matrix with pybind11 (read/write)

This is an implementation of a class containing a vector of Eigen Matrix plus the definition of the python binding.

``````#include <vector>

#include <pybind11/eigen.h>
#include <Eigen/Dense>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;

using EMatrixDbl = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;

class MyMap
{

public:
MyMap(int i, int j)
{
m_matrices.resize(1);
m_matrices[0].resize(i, j);
m_matrices[0].setZero();
}

EMatrixDbl& operator[](int k)
{
return m_matrices[k];
}

EMatrixDbl& get(int k)
{
return m_matrices[k];
}

std::vector<EMatrixDbl> m_matrices;

};

PYBIND11_MODULE(MyMapPy, m) {

py::class_<MyMap> c(m, "MyMap");

c.def(py::init<int, int>());

c.def("get", &MyMap::get, py::return_value_policy::reference_internal);

c.def("get_lambda", [](MyMap& self, int k){
EMatrixDbl& m_map = self[k];
return m_map;
}, py::return_value_policy::reference_internal);
}
``````

When I use the binding, only the method `get` allow to edit the matrix.

1. Why `get_lambda` is not able to do the same?
2. How to bind `MyMap::operator[]` directly to provide a writeable interface of the binding?
``````import MyMapPy
m = MyMapPy.MyMap(3, 3)

m.get(0)[0,0] = 1
m.get(0)  # [0,0] is 1

m.get_lambda(0)[0,0] = 2
m.get_lambda(0)  # [0,0] is always 1...
``````

Solution

• The lambda function return type is deduced to `EMatrixDbl` not `EMatrixDbl&`. Easiest fix is to specify the return type:

``````        [](MyMap& self, int k) -> EMatrixDbl&
``````

Result

``````>>> m.get_lambda(0)[0,0]=2
>>> m.get(0)
array([[2., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
``````

A more general approach is to specify the return type as `decltytpe(auto)` see this answer.