Я пишу программу на C ++, единственная цель которой — вызывать код Matlab. У меня есть основная рутина, которая
читать данные в файле (матрицы с высокой размерностью 90000 * 24) в C ++
сооружения
передать эти структуры в код Matlab
запустить процедуру Matlab с этими структурами в аргументе
получить выходные данные из 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?
Вы уже обнаружили 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 = Существующая_вариабельная;»
Вот вымышленный пример, подобный тому, что вы описали:
#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;
}
Чтобы создать матричное поле в структуре, можно создать временную переменную, а затем присвоить ее значение полю структуры:
// 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);