如何将 Eigen::Ref 与 pybind11 一起使用?

How to use Eigen::Ref with pybind11?

本文关键字:一起 pybind11 Ref Eigen      更新时间:2023-10-16

我正在使用pybind来包装C++代码。

给定以下函数,该函数最初是库的一部分,不应修改:

void manipulate(Eigen::MatrixXd& data) {
data = data*2;
}

使用 pybind,我可以将其包装为:

#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <Eigen/LU>
namespace py = pybind11;
void wrap1(Eigen::Ref<Eigen::MatrixXd> data){
Eigen::MatrixXd mData(data);
manipulate(mData);
data = mData;
}
PYBIND11_PLUGIN(cod) {
pybind11::module m("cod", "auto-compiled c++ extension");
m.def("wrap1", &wrap1);
return m.ptr();
}

但这会产生不必要的复制mData.

这将无法修改数据:

void wrap2(Eigen::MatrixXd& data){
manipulate(data);
}

这个失败编译失败:

void wrap3(Eigen::Ref<Eigen::MatrixXd> data){
manipulate(data);
}

如何避免创建同样datawrap2wrap3或等效std::swap的副本?

这将无法修改数据:

void wrap2(Eigen::MatrixXd& data){

是的,这不会修改原始的numpy数组,因为pybind必须首先将其复制到临时特征矩阵中才能调用wrap2。来自 pybind Eigen 文档:

上述的一个主要限制是每个数据转换都隐式涉及一个副本,这可能既昂贵(对于大型矩阵(,又不允许更改其(矩阵(参数的绑定函数。Pybind11 允许您通过使用 Eigen 的 Eigen::Ref 类来解决此问题...

因此,我们必须使用Eigen::Ref.

这个失败编译失败:

void wrap3(Eigen::Ref<Eigen::MatrixXd> data){
manipulate(data);
}

解决方案是定义一个接受Eigen::Ref的函数:

void manipulate(Eigen::Ref<Eigen::MatrixXd> data) {
data = data*2;
}

另一种选择是将manipulate作为函数模板。请参阅 Eigen 关于编写将特征类型作为参数的函数的文档。