Работа с предварительно выделенными массивами в mex-функции Matlab

Я написал простую функцию mex, которая обновляет уже выделенный массив Matlab:

mex_test_array.c

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *x = mxGetPr(prhs[0]);
    x[0] = 3.1416;
}

Тест 1:

>> y = zeros(2, 2);
>> mex_test_array(y);
>> y

y =

    3.1416         0
         0         0

Тест 2:

>> y = zeros(2, 2);
>> mex_test_array(y(:, 1));
>> y

y =

     0     0
     0     0

Почему это не работает на подматрице (тест 2)? Можно ли заставить его работать?

Пожалуйста, порекомендуйте.

Примечание: я понимаю, что обновление входных массивов - это не то, как ожидается, что файлы mex будут записываться, и я знаю, как возвращать массивы из mex. Причина, по которой я попробовал этот метод, заключается в том, чтобы избежать двойного выделения памяти массивов.


person Serg    schedule 23.03.2012    source источник


Ответы (1)


Это не должно работать, так как MATLAB не хочет изменять "правосторонние параметры". См., например, онлайн-справку:

prhs [это] Массив указателей на входные данные. Входные данные доступны только для чтения и не должны изменяться вашей функцией mexFunction.

Вот почему заголовок вашей функции

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

говорит const mxArray *prhs[], а не mxArray *prhs[]. Если вы хотите вернуть значение, вы должны сделать это через mxArray *plhs[]. Я думаю, что поведение при изменении «правого параметра» просто не определено, и рекомендую прочитать полный руководство по файлам MEX для получения дополнительной информации.

ОБНОВЛЕНИЕ

Чтобы ответить на ваш фактический вопрос, я предполагаю, что когда вы передаете y своей функции, MATLAB передает вам фактический указатель и (ошибочно) доверяет вам не связываться с ним; когда вы передаете свою функцию y(:,1) MATLAB делает копию этой части массива и передает вам указатель на эту копию, которая отбрасывается после вызова вашей функции.

Если вы настаиваете на этом, хотя бы прочитайте Метод редактирования Matlab на месте в недокументированном Matlab, как указано в комментариях reve_etrange! По сути, вы должны запустить

mxUnshareArray(const_cast<mxarray *>(prhs[0]), true); 

прежде чем изменить этот массив. В противном случае работает

>> y = zeros(2, 2);
>> y_backup=y;
>> mex_test_array(y);

приведет к

>> y    
y =    
    3.1416         0
             0         0
>> y_backup
y =    
    3.1416         0
             0         0

... что делает код чертовски непригодным для сопровождения!

person Jonas Heidelberg    schedule 23.03.2012
comment
Однако существуют недокументированные внутренние функции, которые позволяют вам работать с mxArrayс на месте. - person reve_etrange; 24.03.2012
comment
Йонас, я добавил комментарий к своему вопросу (я знаю, что это не нетрадиционный способ). Из вашего ответа, когда вы передаете свою функцию y (:, 1), MATLAB делает копию этой части массива, я предполагаю, что ничего не нужно делать, чтобы разрешить передать mex указатель на фактический y (:, 1)? - person Serg; 25.03.2012