【问题标题】:Call Matlab in C++ code - using methods in engine.h在 C++ 代码中调用 Matlab - 使用 engine.h 中的方法
【发布时间】:2014-11-06 08:28:00
【问题描述】:

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

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

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

  3. 使用参数中的这些结构启动 Matlab 例程

  4. 从 Matlab 获取输出数据并将它们存储在 C++ 结构中

在 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 结构的矩阵类型字段赋值的最佳方法是什么?

【问题讨论】:

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


    【解决方案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;
    }
    

    【讨论】:

      【解决方案2】:

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

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

      从这些函数开始,您可以找到其他直接从 C++ 处理 MATLAB 结构变量的函数,包括 mxCreateStructMatrix()mxSetField()。 MATLAB struct 变量是一种“容器”类型,这意味着每个字段本身就是一个 MATLAB 变量,因此您需要将适当的字段设置为您已经创建的双 mxArray。

      如果您确实需要设置现有结构的字段,您可以像现在一样将变量作为双精度数组。然后,您提到的matlabExecute() 方法是完美的。它只需要您希望 MATLAB 执行的字符串,在本例中为“MATLAB_STRUCT.fieldname = existing_variable;”

      【讨论】:

        【解决方案3】:

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

        // 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);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-08-17
          • 1970-01-01
          • 2013-01-04
          • 1970-01-01
          • 2013-03-10
          • 1970-01-01
          • 2017-11-10
          相关资源
          最近更新 更多