2014-11-06 89 views
0

我編寫了一個C++程序,其唯一目的是調用Matlab代碼。我有一個主程序,其中在C++代碼中調用Matlab - 在engine.h中使用方法

  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結構的矩陣類型字段的最佳方法是什麼?

回答

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

你已經發現了engPutVariable,這是變量插入到發動機工作空間的有效途徑。它可以爲任何類型的mxArray執行此操作,而不僅僅是一個雙重矩陣。

mxCreateDoubleMatrix()mxGetData()是「C/C++矩陣庫API」,這是記錄在這裏的兩個功能:http://www.mathworks.com/help/matlab/cc-mx-matrix-library.html

從那些職能開始,你可以找到其他功能的MATLAB結構變量直接被C處理++包括mxCreateStructMatrix()mxSetField()。一個MATLAB結構變量是一個「容器」類型,這意味着每個字段本身就是一個MATLAB變量,因此您應該將適當的字段設置爲您已經創建的雙mxArray。

如果您確實需要設置現有結構的字段,那麼您可以像當前那樣將該變量設置爲雙數組。然後,你提到的matlabExecute()方法是完美的。它只需要你想讓MATLAB執行的字符串,在這種情況下,它只是「MATLAB_STRUCT.fieldname = existing_variable;」

0

這類似於你所描述的一個虛構的例子:

#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; 
}