用C ++代码调用Matlab - 使用engine.h中的方法

时间:2014-11-06 08:28:00

标签: c++ matlab matrix mex matlab-engine

我编写了一个C ++程序,其唯一目的是调用Matlab代码。我有一个主程序,

  1. 将文件(高维90000 * 24的矩阵)中的数据读入C ++ 结构

  2. 将这些结构传递给Matlab代码

  3. 在参数

  4. 中使用这些结构启动Matlab例程
  5. 从Matlab获取输出数据并将它们存储在C ++结构中

  6. 在2 /中,矩阵是Matlab结构中的字段。结构,比如MATLAB_STRUCT有几个矩阵字段,MATLAB_STRUCT.Z1MATLAB_STRUCT.Z2,...和一些浮点字段MATLAB_STRUCT.flt1,...

    将C ++矩阵(double**)设置为Matlab结构的字段的正确方法是什么?到目前为止,我使用engine.h

    提出了这个问题
        mxArray* labcoeffs_array = convertVectorToMxArray(labcoeffs, 
                                                             coeff_nrows, coeff_ncols); 
        const std::string lab_coeff_name = "MATLAB_STRUCT.labCoef";
        engPutVariable(ep, lab_coeff_name.c_str(), labcoeffs_array);
    

    其中convertVectorToMxArray是我写的将double**转换为mxArray的帮手,

    inline mxArray *convertVectorToMxArray(double** mat, 
                                                  const int nb_rows, const int nb_cols)
    {
        mxArray *outputMxArray = mxCreateDoubleMatrix(
            (int) nb_rows,
            (int) nb_cols,
            mxREAL);
    
        double *data = (double*) mxGetData(outputMxArray);
        for (int r = 0; r < nb_rows; r++)
            for (int c = 0; c < nb_cols; c++)
                data[r + c*nb_rows] = (double)mat[r][c];
    
        return outputMxArray;
    };
    

    但是我已经看到了一些其他技术,用于在Cpp代码中为Matlab结构赋值(尽管不是一个浮点值,而不是矩阵),模仿C ++字符串中的命令行语法:

    std::string setStruct = "MATLAB_STRUCT" + "." + "nB" + " = " + str->nB + ";";
    matlabExecute(ep, setStruct);
    

    ep指向Matlab引擎的指针。

    • 是否可以使用命令行调整此方法,以便为Matlab结构的矩阵类型字段赋值?

    • 将值赋给Matlab结构的矩阵类型字段的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

这是一个类似于你所描述的构成示例:

#include <iostream>
#include <vector>
#include "engine.h"

// create mxArray matrix from an array of data
mxArray* data_to_mxarray(const double *data, int nrows, int ncols)
{
    mxArray *arr = mxCreateDoubleMatrix(nrows, ncols, mxREAL);
    double *x = mxGetPr(arr);
    for (int c=0; c<ncols; c++) {
        for (int r=0; r<nrows; r++) {
            *x = data[r + c*nrows];
            x++;
        }
    }
    return arr;
}

int main()
{
    // step 1: some data
    const char *fieldnames[2] = {"z1", "z2"};
    double z1[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
    double z2[] = {7.0, 8.0, 9.0, 0.0, 1.0, 2.0};

    // open connection to MATLAB
    Engine *ep = engOpen("");

    // create structure with desired fields
    mxArray *st = mxCreateStructMatrix(1, 1, 2, fieldnames);
    mxSetField(st, 0, "z1", data_to_mxarray(z1,2,3));
    mxSetField(st, 0, "z2", data_to_mxarray(z2,3,2));

    // step 2: pass struct to MATLAB workspace
    engPutVariable(ep, "st", st);

    // for the sake of this example, lets create a fake function
    engEvalString(ep, "my_function = @(x) magic(3);");

    // step 3: call some function with the struct as input
    engEvalString(ep, "out = my_function(st);");

    // step 4: retrieve function output
    mxArray *out = engGetVariable(ep, "out");

    // extract data out of it. This depends on the type of output.
    // Say the result was a numeric array
    double *x = mxGetPr(out);
    size_t len = mxGetNumberOfElements(out);
    std::vector<double> v;
    v.resize(len);
    v.assign(x, x+len);
    for (int i=0; i<v.size(); i++) {
        std::cout << v[i] << std::endl;
    }

    // cleanup
    mxDestroyArray(out);
    mxDestroyArray(st);
    engClose(ep);

    return 0;
}

答案 1 :(得分:0)

您已经发现engPutVariable,这是将变量插入Engine工作区的有效方法。它可以为任何类型的mxArray执行此操作,而不仅仅是双矩阵。

mxCreateDoubleMatrix()mxGetData()都是&#34; C / C ++矩阵库API&#34;中的函数,在此处记录:http://www.mathworks.com/help/matlab/cc-mx-matrix-library.html

从这些函数开始,您可以找到直接从C ++处理MATLAB结构变量的其他函数,包括mxCreateStructMatrix()mxSetField()。 MATLAB结构变量是一个&#34;容器&#34; type,表示每个字段本身都是一个MATLAB变量,因此您需要将相应的字段设置为您已经创建的double mxArray。

如果确实需要设置现有结构的字段,可以像现在一样将变量作为双数组。那么,你提到的matlabExecute()方法是完美的。它只需要你希望MATLAB执行的字符串,在这种情况下只是&#34; MATLAB_STRUCT.fieldname = existing_variable;&#34;

答案 2 :(得分:0)

要在结构中创建矩阵字段,一个选项是创建临时变量,然后将其值分配给结构的字段:

// Create temp variable
mxArray* array = convertVectorToMxArray(mat, nb_rows, nb_cols);  
const std::string temp_name = array_name + "_temp";
int ret = engPutVariable(ep, temp_name.c_str(), array);

// Set variable to struct field
const std::string cmd = std::string(array_name + " = " + temp_name + "; ");
matlabExecute(ep, cmd);

// Delete array
mxDestroyArray(array);