Eigen::Matrix 包含在一个结构中被 pybind11 标记为不可写

Eigen::Matrix contained inside a struct is marked as non-writeable by pybind11

我正在使用 pybind11 为使用 Eigen 类型的 C++ 库创建 Python 绑定。但是,当我尝试绑定包含 Eigen::Matrix 的结构时,相应生成的 Python class 具有所有 ndarray(Python 目标 class for Eigen::Matrix members) Writeable 标志设置为 false 的元素,因此这些元素是不可修改的。我已经设法将我的问题减少到以下 MWE:

// binding.cpp
#include "Eigen/Dense"
#include "pybind11/pybind11.h"
#include "pybind11/eigen.h"

struct Example {
   Eigen::Matrix<double, 3, 1> m;
};

namespace py = pybind11;
PYBIND11_MODULE(MyBinding, m)
{
   py::class_<Example>(m, "Example")
      .def(py::init<>())
      .def_readwrite("m", &Example::m);
}
# script.py
import MyBinding
ex = MyBinding.Example()
# ex.m has Writeable flag equal to false!

相反,当绑定以下代码时,一切都按预期工作,即 f 返回的值,当在 Python 中调用时,是可修改的(将 Writeable 标志设置为 true ):

Eigen::Matrix<double,3,1> f() {
   return {};
}

PYBIND11_MODULE(MyBinding, m)
{
   m.def("f", &f);
}

我在这里错过了什么?感谢您的帮助!

def_readwritedef_property (source link) 的快捷方式,其中 getter 通过 const 引用获取 class 实例。因此生成的 numpy 数组是不可修改的。

您需要做的就是编写自定义 getter 和 setter 函数:

namespace py = pybind11;
PYBIND11_MODULE(MyBinding, m)
{
   py::class_<Example>(m, "Example")
      .def(py::init<>())
      .def_property("m", 
           [](Example& example){ return example.m; } // getter 
           [](Example& example, const Eigen::Matrix<double, 3, 1>& value ){ // setter
             example.m = value;
           }
);
}

注意: 未经测试的代码,您可能需要传递额外的 return 值策略参数