用c ++创建2d-array并在matlab中使用它

时间:2013-08-29 15:52:35

标签: c++ matlab

有一个标准示例说明如何在c ++中创建或更改数组并将其用作matlab中的数组:

/*==========================================================
 * arrayProduct.c - example in MATLAB External Interfaces
 *
 * Multiplies an input scalar (multiplier) 
 * times a 1xN matrix (inMatrix)
 * and outputs a 1xN matrix (outMatrix)
 *
 * The calling syntax is:
 *
 *      outMatrix = arrayProduct(multiplier, inMatrix)
 *
 * This is a MEX-file for MATLAB.
 * Copyright 2007-2012 The MathWorks, Inc.
 *
 *========================================================*/
/* $Revision: 1.1.10.4 $ */

#include "mex.h"

/* The computational routine */
void arrayProduct(double x, double *y, double *z, mwSize n)
{
    mwSize i;
    /* multiply each element y by x */
    for (i=0; i<n; i++) {
        z[i] = x * y[i];
    }
}

/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[])
{
    double multiplier;              /* input scalar */
    double *inMatrix;               /* 1xN input matrix */
    size_t ncols;                   /* size of matrix */
    double *outMatrix;              /* output matrix */

    /* get the value of the scalar input  */
    multiplier = mxGetScalar(prhs[0]);

    /* create a pointer to the real data in the input matrix  */
    inMatrix = mxGetPr(prhs[1]);

    /* get dimensions of the input matrix */
    ncols = mxGetN(prhs[1]);

    /* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(1,(mwSize)ncols,mxREAL);

    /* get a pointer to the real data in the output matrix */
    outMatrix = mxGetPr(plhs[0]);

    /* call the computational routine */
    arrayProduct(multiplier,inMatrix,outMatrix,(mwSize)ncols);
}

这基本上就是我想要的,只是我想要更改一个二维数组而不仅仅是一个简单的数组。我尝试创建一个2D数组(4 * n)并更改第4行,看它是否有效。如果我更改以下行:

/* The computational routine */
void arrayProduct(double x, double *y, double *z, mwSize n)
{
mwSize i;
/* multiply each element y by x */
for (i=0; i<n; i++) {
z[3][i] = x * y[i];
}
}

/* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(4,(mwSize)ncols,mxREAL);
它不起作用。我得到错误,z既不是字段也不是指针。任何人都可以告诉我我做错了什么以及我是如何工作的?

3 个答案:

答案 0 :(得分:1)

从根本上说,二维数组总是需要定义它的第一个维度。

将指针(z)视为2d数组会破坏该规则。

如果没有定义第一个维度(实际上除最后一个维度之外的所有维度),则无法正确计算指针的实际偏移量。

在您的代码中,如您所知,每个维度的大小相等,您可以自己计算指针偏移量。

答案 1 :(得分:1)

多维数组仍然存储为单个连续数组,而不是2D C数组。数据按列主顺序排列,这意味着z [0]是元素(1,1),z [1]是元素(2,1)等,一直到z [4 * N-1] < / p>

要从所需的2D索引(行,列)(从0开始)计算线性索引,只需编写idx = column*nrows + row;。这意味着你需要将nrows值传递给你的计算函数。

所以:在名为nrows的计算函数中添加一个额外的参数,并在调用它时传递该值。并将索引z作为1D数组,如上所述。

答案 2 :(得分:1)

发问者可能已经找到答案。但是,对于像我这样从MATLAB转到C ++并想在C ++中使用某些MATLAB功能的人来说,此答案可能有用。

从C ++向MATLAB发送一维数组非常容易,因为有许多在线示例可以向您展示该过程。但是将2D数组发送到MATLAB有点棘手,因为没有足够的可用信息(尤其是使用动态数组)。下面的代码中显示了一个过程。该过程遵循一些简单的步骤,

  1. 用C ++创建2D数组。
  2. 使用engPutVariable_func()(用户定义函数)将2D数组的每一列发送到MATLAB。
  3. 在C ++中使用engEvalString()在MATLAB中将每一列一起附加。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <cmath>
#include <string.h>
#include "engine.h"
#include "mex.h"
#include <armadillo> 
/* I'm using armadillo for convenient matrix operations
 * The process is applicable for other Linear Algebra libraries as well (including STL)
*/

using namespace std;
using namespace arma;

int Create_2DArray_in_Matlab(Engine &m_pEngine, dmat PlotData);
int engPutVariable_func(Engine &m_pEngine, dvec TheVector, string MatVarName);


int main(void)
{
    dmat PlotData(100000, 10, fill::randu);
    /* Our Objective is to Put Matrix "PlotData" in MATLAB workspace*/


    /* Opening Matlab Engine */

    Engine *m_pEngine;
    m_pEngine = engOpen(NULL);
    if (m_pEngine == NULL)
    {
        std::cout << "Error" << std::endl;
        exit(1);
    }
    engSetVisible(m_pEngine, 1);

    engEvalString(m_pEngine, "clc;");
    engEvalString(m_pEngine, "close all;");
    engEvalString(m_pEngine, "clear all;");


    Create_2DArray_in_Matlab(*m_pEngine, PlotData);
    engEvalString(m_pEngine, "open PlotData");

    return 0;

}

int Create_2DArray_in_Matlab(Engine &m_pEngine, dmat PlotData)
{
    /*Approach is to put one column at a time, of a 2D Matrix 
     *in Matlab workspace*/

    int SIZE_Dmat_rows = PlotData.n_rows;
    int SIZE_Dmat_cols = PlotData.n_cols;

    for (int i = 0; i < SIZE_Dmat_cols; i++)
    {
        dvec Temp_Col = PlotData.col(i);
        dvec Col_Number(1); Col_Number(0) = i;
        engPutVariable_func(m_pEngine, Temp_Col, "Temp_Col");
        engPutVariable_func(m_pEngine, Col_Number, "Col_Number");

        engEvalString(&m_pEngine, "PlotData(:, Col_Number + 1) = Temp_Col;");


    }
    return 0;
}


int engPutVariable_func(Engine &m_pEngine, dvec TheVector, string MatVarName)
{
    /*This function will put a column vector in MATLAB Workspace*/

    int SIZE = TheVector.n_rows;

    double *Temp = new double[SIZE];


    for (int i = 0; i < SIZE; i++)
    {
        Temp[i] = TheVector(i);
    }

    char Char_VariableName[1000];
    strcpy(Char_VariableName, MatVarName.c_str());

    /* Creating Matlab Variables*/

    mxArray *TheMatVec = NULL;
    TheMatVec = mxCreateDoubleMatrix(SIZE, 1, mxREAL);
    memcpy((void *)mxGetPr(TheMatVec), (void *)Temp, sizeof(Temp)*SIZE);
    engPutVariable(&m_pEngine, Char_VariableName, TheMatVec);

    delete[] Temp;

    return 0;

}


在一个简单的MATLAB程序中,这就是我们在C ++中所做的

clc
clear all
close all

A = rand(10, 20); 

for i = 1:length(A)
    A_Temp = A(:, i);
    B(:, i) = A_Temp
    A_Temp = [];
end

希望此信息可能有用...

如果有任何疑问和批评,请发表评论。

感谢和问候