Как преобразовать структуру из кода Matlab в код C (используя компилятор Matlab)

Я пытался создать общую библиотеку C с использованием компилятора Matlab, которая некоторое время будет использоваться в качестве подключаемой библиотеки для другого приложения. Недавно я думал, что выполнил эту задачу только для того, чтобы понять, что функция, которую я вызывал из моей новой общей библиотеки "Matlab Compiled", должна была преобразовать свой возврат в структуру C.

Я использовал пример, найденный на сайте Matlab Answers, чтобы помочь мне создать функцию-оболочку level2 для вызова моей функции Matlab, которая должна возвращать структуру. (http://www.mathworks.com/matlabcentral/answers/94715-how-do-i-wrap-matlab-compiler-4-8-r2008a-created-c-dlls-to-create-another-dll)

Моя проблема заключается в части Преобразовать возвращенные данные MATLAB в данные C кода, приведенного ниже. Я могу преобразовать в целые числа, двойные числа, символы и т. д. в порядке, но мне трудно понять, как закодировать преобразование из mxArray, возвращаемого Matlab, в структуру C.

/* Wrapper for level 1 function exported by the MATLAB generated DLL         *
 * This function converts C data to MATLAB data, calls the MATLAB generated  *
 * function in level1.dll and then converts the MATLAB data back into C data */

int wmlfLevel1(double* input2D, int size, char* message, double** output2d){
    int nargout=1;

    /* Pointers to MATLAB data */
    mxArray *msg;
    mxArray *in2d;
    mxArray *out2d=NULL;

    /* Start MCR, load library if not done already */
    int returnval=isMCRrunning();
    if(!returnval)
        return returnval;

    /* Convert C data to MATLAB data */
    /* IMPORTANT: this has to be done after ensuring that the MCR is running */
    msg=mxCreateString(message);
    in2d=mxCreateDoubleMatrix(size, size, mxREAL);
    memcpy(mxGetPr(in2d), input2D, size*size*sizeof(double));

    /* Call the M function */
    returnval=mlfLevel1(nargout, &out2d, in2d, msg);

    /*Convert returned  MATLAB data to C data */
    *output2d=(double *)malloc(sizeof(double)*size*size);
    memcpy(*output2d, mxGetPr(out2d), size*size*sizeof(double));

    /* Clean up MATLAB variables */
    mxDestroyArray(msg);
    mxDestroyArray(in2d);
    mxDestroyArray(out2d);

    return returnval;
}

До сих пор я пытался использовать функцию mxCreateStructMatrix, я пытался создать скелет структуры C, я собираюсь попробовать функцию libstruct, но, поскольку я новичок в программировании на C и компиляторе Matlab, любая помощь будет очень признательна!


person Dingess    schedule 15.01.2015    source источник


Ответы (1)


mxGetPr просто возвращает указатель на буфер двойников. Вызов malloc выделяет достаточно места для хранения удвоений size^2. memcpy копирует данные из внутренней памяти out2d в ваш буфер.

Буфер одномерный, поэтому вам придется вычислять индекс на основе строки и столбца. Вы можете использовать что-то вроде output2d[col * size + row] для доступа к определенному значению. (Это может быть перенесено - у меня сейчас нет доступа к документам.)

Когда вы полностью закончите с output2d, вам нужно будет вызвать free(output2d) для освобождения памяти, иначе в вашем коде будет утечка памяти.

person Katie    schedule 15.01.2015
comment
Спасибо, Кэти, у меня есть еще несколько вопросов, которые мне нужно прояснить. Нужно ли мне изменить вызов malloc для выделения пространства в соответствии со структурой типа, поскольку это тип, в котором я хочу хранить свои данные. Я хочу, чтобы мои данные были скопированы из out2d в структуру, аналогичную приведенной ниже, как это изменится мой код? Нужно ли сначала настроить структуру C, а затем использовать memcpy для перемещения в нее данных out2d? 'структура output2d { int variable1; двойной переменный2; символьная переменная3[10]; }' - person Dingess; 15.01.2015
comment
Вашей структуре потребуется место для хранения данных. Если вы не знаете size заранее, вам все равно нужно malloc это сделать. (Если вы это знаете, вы можете объявить двумерный массив фиксированного размера.) Структура должна содержать что-то вроде элемента double* matrix для ваших данных. Затем вы можете сделать output2d.matrix = malloc(sizeof(double) * size * size) и memcpy(output2d.matrix, mxGetPtr.... - person Katie; 15.01.2015
comment
Я использовал этот пример, чтобы показать свою проблему, в своем коде я вычисляю структуру с 13 полями данных, некоторые из них просто целые числа, некоторые представляют собой массивы (матрицы в Matlab), а одно представляет собой строку. Если бы я сначала определил структуру, выполнил бы я затем output2d.element1 = malloc(sizeof(element1'stype)*size*size)), memcpy(output2d.element1,mxGetpr(out2d)... и повторил бы для всех 13 полей? - person Dingess; 16.01.2015
comment
Структуры Matlab являются динамическими и используют строки для идентификации полей. Если вы хотите, чтобы mlfLevel1 выводил в структуру, вам нужно разобрать структуру Matlab и собрать ее в структуру C. Я не рекомендую использовать malloc в этом случае, попробуйте mxMalloc: mathworks.com/help/matlab/apiref/mxmalloc.html?refresh=true - person user3528438; 16.01.2015
comment
@user3528438 user3528438, спасибо за совет, я пошел дальше и заменил это там, где это необходимо, и решил просто заставить mlfLevel1 возвращать данные в отдельные переменные, а затем присваивать эти значения структуре C. Я предполагаю, что это то, что вы имели в виду, разбирая структуру Matlab и собирая ее в структуру C. В любом случае, благодаря вам я нашел способ обойти свою проблему, так что ура! - person Dingess; 20.01.2015