使用元胞数组在 C++ 特征矩阵和 MATLAB mxArray 之间传递数据
pass data between C++ Eigen Matrix and MATLAB mxArray with a cell array
我想在 Eigen Matrix/Vector 和 mex 数组之间传递数据。在下面的代码中,我定义了一个名为 y_output 的 mex 数组,其中包含一个元胞数组。变量 y_output 将传递给 MATLAB。 y_output 中的每个元素都是一个向量,但长度不同。我想将指向特征向量的指针传递给 mex 数组 y_output。
注意存储在y中的数据将被用户定义的函数修改。调用该函数后,我假设存储在 y_output 中的数据将被相应地修改。但是,我不能直接将指针从 y_output 传递给 y。有什么办法让它成为可能吗?谢谢!
这个问题与 中的问题相似但不同。这个问题是问如何传递矩阵数组,而link中的问题是问如何传递矩阵。
#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;
}
我想出了一个方法来实现我想要的。关键的一步是先调用自己的函数,最后把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;
}
您的解决方案为 MyFunc
的输入和输出复制数据。可以使用 std::vector
of Eigen::Map
对象来传递两个参数。以下代码基于您的回答。以 //--
开头的行已从您的代码中删除并替换为后面的行。
作为旁注:避免使用 new
分配数组(在所有情况下的 99.99%),而是使用 std::vector
。这负责在对象超出范围时释放所有资源。
此外,在 MyFunc
中,您不必猜测 y
和 z
.
的大小
#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;
}
我想在 Eigen Matrix/Vector 和 mex 数组之间传递数据。在下面的代码中,我定义了一个名为 y_output 的 mex 数组,其中包含一个元胞数组。变量 y_output 将传递给 MATLAB。 y_output 中的每个元素都是一个向量,但长度不同。我想将指向特征向量的指针传递给 mex 数组 y_output。
注意存储在y中的数据将被用户定义的函数修改。调用该函数后,我假设存储在 y_output 中的数据将被相应地修改。但是,我不能直接将指针从 y_output 传递给 y。有什么办法让它成为可能吗?谢谢!
这个问题与
#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;
}
我想出了一个方法来实现我想要的。关键的一步是先调用自己的函数,最后把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;
}
您的解决方案为 MyFunc
的输入和输出复制数据。可以使用 std::vector
of Eigen::Map
对象来传递两个参数。以下代码基于您的回答。以 //--
开头的行已从您的代码中删除并替换为后面的行。
作为旁注:避免使用 new
分配数组(在所有情况下的 99.99%),而是使用 std::vector
。这负责在对象超出范围时释放所有资源。
此外,在 MyFunc
中,您不必猜测 y
和 z
.
#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;
}