Как да конвертирате структура от Matlab код в C код (с помощта на Matlab Compiler)

От известно време се опитвам да създам C споделена библиотека с помощта на компилатор Matlab, който ще се използва като добавка в библиотека към друго приложение. Наскоро си помислих, че съм изпълнил тази задача само за да осъзная, че функцията, която извиквах от моята нова споделена библиотека „Компилирана от Matlab“, трябваше да преобразува връщането си в C структура.

Използвах примера, намерен на сайта на Matlab Answers, за да ми помогне да създам функцията wrapper 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 данни на кода, който се намира по-долу. Мога да преобразувам в int, doubles, chars и т.н. добре, но имам проблеми да разбера как да кодирам преобразуването от 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 doubles. memcpy копира данните от вътрешната памет на out2d и във вашия буфер.

Буферът е едномерен, така че ще трябва да изчислите индекса въз основа на реда и колоната. Можете да използвате нещо като output2d[col * size + row] за достъп до конкретна стойност. (Това може да бъде транспонирано - в момента нямам достъп до документите.)

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

person Katie    schedule 15.01.2015
comment
Благодаря Кейти, имам още няколко въпроса, които трябва да изясня. Трябва ли да променя извикването на malloc, за да разпределя място според структурата на типа, тъй като това е типът, в който искам данните ми да се съхраняват. Искам данните ми да бъдат копирани от out2d в структура, подобна на тази по-долу, как ще се промени това моят код? Трябва ли първо да настроя C структура и след това да използвам memcpy, за да преместя моите out2d данни в нея? 'struct output2d { int variable1; двойно променлив2; char променлива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, благодаря за съвета, продължих и го заместих, където е необходимо, и реших просто да накарам mlfLevel1 да върне данните в отделни променливи и след това да присвои тези стойности на C структура. Предполагам, че това имахте предвид, като разглобихте структурата на Matlab и я сглобихте отново в C структура. Така или иначе намерих начин да заобиколя проблема си благодарение на вас, така че Наздраве! - person Dingess; 20.01.2015