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

Я написал простую функцию 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. Причина, по которой я попробовал эту технику, состоит в том, чтобы избежать выделения памяти массивов дважды.

1 Ответ

5 голосов
/ 24 марта 2012

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

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

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

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

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

UPDATE

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

Если вы настаиваете на этом , по крайней мере прочитайте Редактирование на месте Matlab mex на недокументированном 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

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

...