Working with preallocated arrays in Matlab's m

2019-01-28 11:03发布

问题:

I wrote a simple mex function which updates already allocated by Matlab array:

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;
}

Test 1:

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

y =

    3.1416         0
         0         0

Test 2:

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

y =

     0     0
     0     0

Why it doesn't work on sub-matrix (Test 2) ? Is it possible to make it work?

Please advise.

Remark: I understand, that updating input arrays is not how mex files are expected to be writted, and I do know how to return arrays from mex. The reason I tried this technique is to avoid allocation of the arrays' memory twice.

回答1:

This shouldn't work, since MATLAB does not want "right-hand-side parameters" to change. See for example the online help:

prhs [is an] Array of pointers to input data. The input data is read-only and should not be altered by your mexFunction .

That is why your function header

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

says const mxArray *prhs[] and not mxArray *prhs[]. If you want to return a value, you are supposed to do that through mxArray *plhs[]. I think the behaviour for when you change a "right-hand-side parameter" is just undefined and recommend reading the full MEX files guide for further details.

UPDATE

To answer your actual question, I assume that when you hand y to your function, MATLAB hands you the actual pointer and (falsely) trusts you not to mess with it; when you hand your function y(:,1) MATLAB makes a copy of that part of the array and hands you a pointer to that copy, which is discarded after your function call.

If you do insist on doing this, at least read Matlab mex in-place editing on Undocumented Matlab, as pointed out in the comments by reve_etrange! Essentially, you must run

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

before you modify that array. Otherwise running

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

will result in

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

... which makes for some hell-of-a-unmaintainable code!



标签: matlab mex