在带有单元格数组的C 特征矩阵和MATLAB MXARRAY之间传递数据

pass data between C++ Eigen Matrix and MATLAB mxArray with a cell array

本文关键字:MXARRAY MATLAB 之间 数据 单元格 数组 特征      更新时间:2023-10-16

我想传递eigen矩阵/矢量和mex数组之间的数据。在以下代码中,我定义了一个名为y_output的MEX数组,该数组包含一个单元格数组。变量y_output将传递给MATLAB。y_output中的每个元素都是向量,但长度不同。我想将指向特征向量指向MEX数组y_output的指针。

请注意,存储在Y中的数据将通过用户定义的函数进行修改。调用该函数后,我假设存储在y_output中的数据将被修改相应。但是,我无法将指针从y_output直接传递到y。有什么办法使它成为可能吗?谢谢!

这个问题与PASS C 特征矩阵到MATLAB MEX输出相似,但与Pass C 特征矩阵的问题不同。这个问题是问如何通过一系列矩阵,而该链接中的问题是在询问如何通过矩阵。

#include "mex.h"
#include "matrix.h"
#include <Eigen>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

// prhs[0]: a cell array of length T, each element is a vector with different lengths
mwSize T =  mxGetNumberOfElements(prhs[0]);
mwSize* n = new mwSize[T];
Eigen::VectorXd* z = new Eigen::VectorXd[T];
for(int t=0; t<T; t++){
    n[t] = mxGetNumberOfElements(mxGetCell(prhs[0], t));
    z[t] = Eigen::Map<Eigen::VectorXd>(mxGetPr(mxGetCell(prhs[0], t)), n[t]);
}
// create a cell matrix with T rows and one columns
mxArray* y_output = mxCreateCellMatrix(T,1);
// create corresponding Eigen objects
Eigen::VectorXd* y = new Eigen::VectorXd[T]();
Eigen::VectorXd y_temp(n[0]); y_temp.setZero();
for(int t=0; t<T; t++){
    mxSetCell(y_output, t, mxCreateDoubleMatrix(n[t], 1, mxREAL));
    y[t] = Eigen::VectorXd::Zero(n[t]);
    y_temp.resize(n[t]);
    Eigen::Map<Eigen::VectorXd> y[t](mxGetPr(mxGetCell(y_output, t)), n[t]); // This is not correct!

}

// Myfun(y, z);
// set output
plhs[0] = y_output;
}

您的解决方案将围绕MyFunc输入和输出的数据复制。可以使用Eigen::Map对象的std::vector传递两个参数。以下代码基于您的答案。以//--开头的行已从您的代码中删除,并由随后的行取代。

作为旁注:避免使用new分配数组(在所有情况的99.99%中),但使用std::vector。当对象脱离范围时,这要处理所有资源。另外,在MyFunc中,您不必猜测yz的大小。

#include "mex.h"
#include "matrix.h"
//-- #include <Eigen> <-- this should be <Eigen/Eigen>, but likely Eigen/Core suffices
//                        Perhaps you also need to change your include-path 
#include <Eigen/Core>
#include <vector>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    // prhs[0]: a cell array of length T, each element is a vector with different lengths
    mwSize T =  mxGetNumberOfElements(prhs[0]);
    //-- mwSize* n = new mwSize[T];
    std::vector<mwSize> n(T);
    //-- Eigen::VectorXd* z = new Eigen::VectorXd[T];
    std::vector<Eigen::Map<const Eigen::VectorXd> > z; // input vector of Maps
    z.reserve(T);
    for(int t=0; t<T; t++){
        // Note: You don't actually seem to need n[t], except for creating y_output
        n[t] = mxGetNumberOfElements(mxGetCell(prhs[0], t));
        //-- z[t] = Eigen::Map<Eigen::VectorXd>(mxGetPr(mxGetCell(prhs[0], t)), n[t]);
        z.emplace_back(mxGetPr(mxGetCell(prhs[0], t)), n[t]);
    }
    // create a cell matrix with T rows and one columns
    mxArray* y_output = mxCreateCellMatrix(T,1);
    // create corresponding Eigen objects
    //-- Eigen::VectorXd* y = new Eigen::VectorXd[T]();
    std::vector<Eigen::Map<Eigen::VectorXd> > y; // output vector of Maps
    y.reserve(T);
    // This must be called after setting up y: 
    //-- Myfun(y, z);
    //-- double* ptemp;
    for(int t=0; t<T; t++){
        mxSetCell(y_output, t, mxCreateDoubleMatrix(n[t], 1, mxREAL));
        //-- ptemp = mxGetPr(mxGetCell(y_output, t));
        //-- // assign the data stored in y[t] to the contents in y_output.
        //-- for(int i=0; i<n[t]; i++){
        //--     //mxGetPr(mxGetCell(y_output, t))[i] = y[t](i);
        //--     ptemp[i] = y[t](i);
        //-- }
        y.emplace_back(mxGetPr(mxGetCell(y_output, t)), n[t]);
    }
    // Now call Myfun, but the function now needs to accept vectors of Eigen::Map, instead of pointers to VectorXd
    // It should be possible to keep the Code inside Myfun unchanged
    // Myfun(y, z);
    //-- ptemp = NULL;
    // set output
    plhs[0] = y_output;
}

我已经找到了一种实现我想要的方法的方法。关键步骤是首先调用我自己的功能,最后,将y中存储的数据分配给y_output。我在下面包含了修改的代码,以便它对感兴趣的任何人都有帮助。

#include "mex.h"
#include "matrix.h"
#include <Eigen>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

// prhs[0]: a cell array of length T, each element is a vector with different lengths
mwSize T =  mxGetNumberOfElements(prhs[0]);
mwSize* n = new mwSize[T];
Eigen::VectorXd* z = new Eigen::VectorXd[T];
for(int t=0; t<T; t++){
    n[t] = mxGetNumberOfElements(mxGetCell(prhs[0], t));
    z[t] = Eigen::Map<Eigen::VectorXd>(mxGetPr(mxGetCell(prhs[0], t)), n[t]);
}
// create a cell matrix with T rows and one columns
mxArray* y_output = mxCreateCellMatrix(T,1);
// create corresponding Eigen objects
Eigen::VectorXd* y = new Eigen::VectorXd[T]();

 // Myfun(y, z);
double* ptemp;
for(int t=0; t<T; t++){
    mxSetCell(y_output, t, mxCreateDoubleMatrix(n[t], 1, mxREAL));
    ptemp = mxGetPr(mxGetCell(y_output, t));
    // assign the data stored in y[t] to the contents in y_output.
    for(int i=0; i<n[t]; i++){
        //mxGetPr(mxGetCell(y_output, t))[i] = y[t](i);
        ptemp[i] = y[t](i);
    }

}
ptemp = NULL;

// set output
plhs[0] = y_output;
}