c – 使用Eigen :: Map作为Eigen :: MatrixXd类型的函数参数

简而言之,问题是如何通过

Eigen::Map<Eigen::MatrixXd>

对象期望a的函数

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传递给一个需要非const 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))

最佳答案 将它作为普通指针传递给数据,然后将Eigen :: Map映射到那里.或者,使用模板< typename Derived>等,发现于
http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html

我个人的选择是第一个,因为最好让代码不会暴露你所使用的每个API的所有顽固性.此外,您不会失去与eigen的兼容性,也不会失去您(或其他任何人)稍后可能使用的任何其他类型的库.

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

Eigen :: MatrixXd a;
//让我们假设一个数据指针,比如我们要映射的double * DATA
//现在我们做
new(& a)Eigen :: Map< Eigen :: Matrix< Double,Eigen :: Dynamic,Eigen :: Dynamic>> (DATA,DATA行,DATA cols);

这将按照你的要求做,而不会浪费记忆.我认为这是一个很酷的技巧,并且会表现为matrixXd,但我没有测试过每一次.它没有内存副本.但是,您可能需要在分配之前将大小调整为正确的大小.即便如此,编译器也不会在您请求调整大小操作时立即分配所有内存,因此也不会有大量无用的内存分配!

Be careful! Resizing operations might reallocate the memory used by an eigen matrix! So, if you ::Map a memory but then you perform an action that resizes the matrix, it might be mapped to a different place in memory.

点赞