0

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

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

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

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

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

在 2/ 中,矩阵是 Matlab 结构中的字段。说,该结构MATLAB_STRUCT有几个矩阵字段,,,MATLAB_STRUCT.Z1...MATLAB_STRUCT.Z2和一些浮点字段MATLAB_STRUCT.flt1,...

double**将 C++ 矩阵 ( ) 设置为 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);

我写的要转换为 aconvertVectorToMxArray的助手在哪里,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 结构的矩阵类型字段赋值的最佳方法是什么?

4

3 回答 3

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;
}
于 2014-11-09T09:47:59.053 回答
0

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

mxCreateDoubleMatrix()并且mxGetData()都是“C/C++ Matrix Library API”中的两个函数,记录在这里: http: //www.mathworks.com/help/matlab/cc-mx-matrix-library.html

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

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

于 2014-11-06T14:09:46.817 回答
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);
于 2014-11-14T15:27:02.787 回答