C++ 使用Eigen::Map<;特征::矩阵xD>;作为本征::矩阵XXD类型的函数参数

C++ 使用Eigen::Map<;特征::矩阵xD>;作为本征::矩阵XXD类型的函数参数,c++,numpy,eigen3,C++,Numpy,Eigen3,简言之,问题是如何通过考试 Eigen::Map<Eigen::MatrixXd> 反对 长话短说: 我有这个C++函数声明< /p> void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result); 连同这项实施 void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result) { //Just do s

简言之,问题是如何通过考试

Eigen::Map<Eigen::MatrixXd>
反对


长话短说:

我有这个C++函数声明< /p>

void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result);
连同这项实施

void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result)
{
//Just do s.th. with arguments
std::cout << data << std::endl;

result(1,1) = -5;
std::cout << result << std::endl;
}
它获取指向数据的指针、数据数组的大小、指向结果的指针以及结果数组的大小。数据指针指向内存的常量补丁,因为在为结果保留的内存补丁是可写的情况下,数据不会被更改。功能的实现

void pyMatrix(const double *p_data, const int dimData[], double *p_result, const int dimResult[])
{
Eigen::Map<const Eigen::MatrixXd> dataMap(p_data, dimData[0], dimData[1]);
Eigen::Map<Eigen::MatrixXd> resultMap(p_result, dimResult[0], dimResult[1]);

resultMap(0,0) = 100;

npMatrix(dataMap, resultMap);
}
显示,结果映射实际上是可写的。在将dataMap传递到npMatrix()时,我找不到一种方法以同样的方式传递resultMap,而npMatrix()需要const-Eigen::MatrixXd。我确信,问题来自这样一个事实,npMatrix的第一个参数是const,而第二个参数不是。我发现一个可能的解决方案是定义

Eigen::MatrixXd resultMatrix = resultMap;
并将此ResultMatrix传递给npMatrix()。然而,我想,这会创建一个副本,从而终止了Eigen::Map的良好内存映射。所以我的问题是

有没有办法将一个Eigen:Map传递给一个需要非常量Eigen::MatrixXd的函数

作为旁注:我可以将npMatrix更改为期望一个Eigen::Map,但是因为在实际项目中,函数已经存在并经过测试,所以我不想对它们进行调整

为了完成这个问题,下面是调用pyMatrix()的python文件


将其作为指向数据的普通指针传递,并将其映射到那里。或者,使用
模板
等,如 不过,我个人的选择是第一个,因为最好不要让代码暴露您所使用的每个API的顽固性。此外,您不会失去与eigen的兼容性,也不会失去与您(或任何其他人)以后可能使用的任何其他类型的库的兼容性

我还发现了另一个技巧,可以在很多场合使用:

Eigen::MatrixXd a;
//让我们假设一个数据指针,比如我们想要映射的double*数据
//现在我们知道了
新(&a)特征::映射(数据、数据行、数据列)

这将满足您的要求,而不会浪费内存。我认为这是一个很酷的把戏,
a
会表现得像matrixXd一样,但我并不是每次都测试过它没有内存副本。但是,在分配之前,您可能需要将
a
调整到正确的大小。即使如此,编译器也不会在您请求
resize
操作时立即分配所有内存,因此也不会有大量无用的内存分配

小心!调整大小操作可能会重新分配特征矩阵使用的内存因此,如果您::映射内存,但随后执行调整矩阵大小的操作,则可能会将其映射到内存中的其他位置


对于仍在努力解决将
Eigen::Map
传递给具有签名的函数
Eigen::Matrix
或反之亦然的问题的任何人,他们发现@Aperture Laboratories建议的
Eigen::Matrix
Eigen::Map
隐式投射技巧不起作用(在我的例子中,这给出了与尝试释放已释放内存相关的运行时错误,[与
valgrind
]一起运行时出现不匹配的删除/无效的删除错误]

我建议对函数签名使用
Eigen::Ref
类,如@ggael给出的答案所示:

并写在文件中: 标题下:

如何编写通用但非模板化的函数

例如,对于问题中指定的函数,将签名更改为

void npMatrix(const Eigen::Ref<const Eigen::MatrixXd> & data, Eigen::Ref< Eigen::MatrixXd> result);
void npMatrix(const-Eigen::Ref&data,Eigen::Ref结果);
意味着将
Eigen::Map
Eigen::MatrixXd
对象传递到函数将无缝工作(有关在函数签名中使用Eigen::Ref的不同方法,请参阅@ggael的答案)


我很感激OP说他不想更改函数签名,但就互换使用
Eigen::Map
s和
Eigen::Matrix
而言,我发现这是最简单、最可靠的方法。

谢谢你的回答。我接受了它,因为我认为,总体而言,这是一个好的解决方案。正如我在问题中所说的,我认为o不想更改要调用的函数的接口。因此,我的解决方案是创建所需的映射。这会导致内存和cpu时间的浪费,但与程序的其余部分相比,这并不重要。谢谢!我考虑了更多,我想我找到了另一个答案,它将完全满足您的要求,并且不会更改f函数声明。我会更新我的答案!已经18个月了,但是有这么多有用的信息。这里
new(&a)
是放置版本,因此我相信从
Map
Matrix
对象的转换是隐含的(如果我错了,请纠正我)。我猜您所指的调整大小是指
a
不是数据的所有者,因此无法使用赋值
运算符=
为其分配另一个矩阵。我通过跟踪数据的所有权来实现这一点-最初
a
可能不拥有数据,但在赋值之前,当它不是所有者或e当前大小不正确。
<const Eigen::MatrixXd>
<Eigen::MatrixXd>
resultMap(0,0) = 100;
Eigen::MatrixXd resultMatrix = resultMap;
import ctypes as ct
import numpy as np
import matplotlib.pyplot as plt

# Load libfit and define input types
ct.cdll.LoadLibrary("/home/wmader/Methods/fdmb-refactor/build/pyinterface/libpyfit.so")
libfit = ct.CDLL("libpyfit.so")

libfit.pyMatrix.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64, ndim=2),
                                                     np.ctypeslib.ndpointer(dtype=np.int32, ndim=1),
                                                     np.ctypeslib.ndpointer(dtype=np.float64, ndim=2, flags='WRITEABLE'),
                                                     np.ctypeslib.ndpointer(dtype=np.int32, ndim=1)
                                                     ]

data = np.array(np.random.randn(10, 2), dtype=np.float64, order='F')
result = np.zeros_like(data, dtype=np.float64, order='F')

libfit.pyMatrix(data, np.array(data.shape, dtype=np.int32),
                              result, np.array(result.shape, dtype=np.int32))
void npMatrix(const Eigen::Ref<const Eigen::MatrixXd> & data, Eigen::Ref< Eigen::MatrixXd> result);