简而言之,问题是如何通过
Eigen::Map<Eigen::MatrixXd>
对象期望一个函数
Eigen::MatrixXd
目的。
更长的故事:
我有这个 C++ 函数声明
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;
}
我想使用 numpy.array 作为参数从 python 调用这个函数。为此,我使用了一个用 c++ 编写的包装函数
void pyMatrix(const double* p_data, const int dimData[],
double* p_result, const int dimResult[]);
它接受指向数据的指针、数据数组的大小、指向结果的指针以及结果数组的大小。数据指针指向一个 const 内存块,因为当为结果保留的内存块是可写的时,数据不会被更改。函数的实现
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);
}
分别为数据和结果定义了一个 Eigen::Map。Eigen::Map 允许将原始内存作为一种 Eigen::Matrix 访问。dataMap 的类型
<const Eigen::MatrixXd>
因为相关的内存是只读的;相比之下,resultMap 是类型
<Eigen::MatrixXd>
因为它必须是可写的。线
resultMap(0,0) = 100;
显示,resultMap 确实是可写的。在将 dataMap 传递给预期 const Eigen::MatrixXd 工作的 npMatrix() 时,我找不到以相同方式传递 resultMap 的方法。我敢肯定,麻烦来自这样一个事实,npMatrix 的第一个参数是 const,而第二个不是。我发现的一个可能的解决方案是定义
Eigen::MatrixXd resultMatrix = resultMap;
并将这个 resutlMatrix 传递给 npMatrix()。但是,我想,这会创建一个副本,因此会破坏 Eigen::Map 的良好内存映射。所以我的问题是。
有没有办法将 Eigen:Map 传递给一个需要非常量 Eigen::MatrixXd 的函数?
附带说明:我可以将 npMatrix 更改为期望 Eigen::Map,但由于在实际项目中,函数已经存在并经过测试,因此我宁愿不使用它们。
为了完成这个问题,这里是调用 pyMatrix() 的 python 文件
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))