Вызов Matlab в коде C ++ — использование методов в engine.h

Я пишу программу на 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, …

Какой правильный подход для установки матриц 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;
};

Но я видел другой способ присвоения значения структуре Matlab в коде Cpp (хотя значение с плавающей запятой, а не матрица), имитирующего синтаксис командной строки в строке C ++:

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

с ep указатель на движок Matlab.

  • Можно ли адаптировать этот подход с командной строкой для присвоения значения полю типа матрицы структуры Matlab?

  • Каков наилучший подход для присвоения значения полю матричного типа структуры Matlab?

0

Решение

Вы уже обнаружили engPutVariable, который является эффективным способом вставки переменных в рабочую область Engine. Это может сделать это для mxArray любого типа, а не только для двойной матрицы.

mxCreateDoubleMatrix() а также mxGetData() обе функции в «C / C ++ Matrix Library API», который описан здесь: http://www.mathworks.com/help/matlab/cc-mx-matrix-library.html

Начиная с этих функций, вы можете найти другие функции для работы со структурными переменными MATLAB непосредственно из C ++, в том числе mxCreateStructMatrix() а также mxSetField(), Переменная структуры MATLAB является типом «контейнер», то есть каждое поле само является переменной MATLAB, поэтому вы должны установить соответствующее поле в двойной созданный вами массив mxArray.

Если вам действительно нужно установить поле существующей структуры, вы можете поместить переменную в виде двойного массива, как в настоящее время. Затем matlabExecute() подход, о котором вы упоминаете, идеален. Он просто берет строку, которую вы хотите, чтобы MATLAB выполнил, которая в данном случае просто «MATLAB_STRUCT.fieldname = Существующая_вариабельная;»

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;
}
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
По вопросам рекламы [email protected]