我正在使用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);
}
如何避免像data
,wrap2
或等效的wrap3
一样创建std::swap
的副本?
答案 0 :(得分:1)
这无法修改数据:
void wrap2(Eigen::MatrixXd& data){
是的,这不会修改原始的numpy数组,因为pybind必须首先将其复制到临时的本征矩阵中才能调用wrap2
。来自https://outlook.live.com/mail/inbox:
上述内容的一个主要限制是,每个数据转换都隐式地涉及一个副本,这可能既昂贵(对于大型矩阵),又不允许绑定函数更改其(矩阵)参数。 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
成为功能模板。请参阅pybind Eigen docs上的Eigen文档。