Mexfunction variables error in structured variable array

I recently tried to write mexfunctions using structured variables. I watched the tutorial but got confused due to how variable values ​​are passed. The following example ( mexfunction_using_ex_wrong.m & mexfunction_using_ex_wrong.cpp

) demonstrates how to retrieve the variables passed from matlab to mexfunction. However, in this case, the result is:

address i_c1=2067094464 i_c2=2067094464
        i_c1=10         i_c2=10
address i_c1=1327990656 i_c2=2067100736
        i_c1=2          i_c2=20
address i_c1=2067101056 i_c2=2067063424
        i_c1=3          i_c2=30

      

As you can see, the first element of the array c1 and c2 of the structure variable coincides by chance.

But in another example ( mexfunction_using_ex_correct.m & mexfunction_using_ex_correct.cpp

) the elements of array 1 (b1) and array 2 (b2) of the structure variable are not related as I expect. Result:

address i_b1=1978456576 i_b2=1326968576
        i_b1=1          i_b2=10
address i_b1=1978456584 i_b2=1326968584
        i_b1=2          i_b2=20
address i_b1=1978456592 i_b2=1326968592
        i_b1=3          i_b2=30

      

However, the first programming example is most often used. so can someone explain why in 1st example the addresses i_c1 and i_c2 are the same?

The following code: mexfunction_using_ex_wrong.m

clc
clear all
close all

mex mexfunction_using_ex_c_wrong.cpp;

a.b(1).c1=double(1);
a.b(2).c1=double(2);
a.b(3).c1=double(3);

a.b(1).c2=double(1);
a.b(2).c2=double(2);
a.b(3).c2=double(3);

mexfunction_using_ex_c_wrong(a);

      

The following code: mexfunction_using_ex_c_wrong.cpp

#include "mex.h"

void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) 
{   
     int i, j, k;

     double *i_c1;
     double *i_c2;

     // for struct variables(pointers) inside fcwcontext
     mxArray *mx_b, *mx_c1, *mx_c2;    

     mx_b=mxGetField(prhs[0], 0, "b");

    for(i = 0;i < 3;i=i+1)
    {               
        mx_c1=mxGetField(mx_b, i, "c1");
        mx_c2=mxGetField(mx_b, i, "c2");

        i_c1=mxGetPr(mx_c1);
        i_c2=mxGetPr(mx_c2);        

        *i_c2=(*i_c2)*10;

        printf("address i_c1=%d i_c2=%d\n", i_c1, i_c2);
        printf(" i_c1=%g i_c2=%g\n", *i_c1, *i_c2);               
    }                  
}

      

The following code: mexfunction_using_ex_c_correct.m

clc
clear all
close all

mex mexfunction_using_ex_correct.cpp;

a.b1(1)=double(1);
a.b1(2)=double(2);
a.b1(3)=double(3);

a.b2(1)=double(1);
a.b2(2)=double(2);
a.b2(3)=double(3);

mexfunction_using_ex_correct(a);

      

The following code: mexfunction_using_ex_c_correct.cpp

#include "mex.h"

void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) 
{   
     int i, j, k;

     double *i_b1;
     double *i_b2;

     mxArray *mx_b1, *mx_b2;    

     mx_b1=mxGetField(prhs[0], 0, "b1");
     mx_b2=mxGetField(prhs[0], 0, "b2");

    for(i = 0;i < 3;i=i+1)
    {                       
        i_b1=mxGetPr(mx_b1);
        i_b2=mxGetPr(mx_b2);        

        i_b2[i]=i_b2[i]*10;

        printf("address i_b1=%d i_b2=%d\n", &i_b1[i], &i_b2[i]);
        printf(" i_b1=%g i_b2=%g\n", i_b1[i], i_b2[i]);                
    }                  
}

      

+3


source to share


1 answer


The addresses are not "accidentally the same" —they are intentionally the same, due to MATLAB's internal copy-for-write optimizations. If you look at the MEX documentation, you will see warnings scattered around ...

Do not change the values prhs

in the MEX file. Modifying the data in these read-only mxArracs can lead to unwanted side effects.

... in various forms ...

Note The entries in the MEX file are permanent read-only mxArrays. Don't change the inputs. Using functions mxSetCell*

or mxSetField*

to change cells or fields of a MATLAB® argument produces unpredictable results.



... trying to figure out that you absolutely shouldn't change whatever you get as input. By calling mxGetPr()

on the input data and writing back to that pointer, as you do with i_b2

and i_c2

, you get straight into this territory with "unpredictable results" - if you look at a.b(1).c1

in the MATLAB workspace after the call it will indeed be 10, even if you "only" changed c2

.

From MEX you are browsing the raw data store without any knowledge or internal access to MATLAB, so the only safe way to change anything is to use functions mxCreate*

or mxDuplicate*

to get your own safe arrays, you can do whatever you want and go to MATLAB via plhs

...

However, I would settle for abusing in-place modification to dramatically improve performance in a single instance, where I could ensure that my data was unique and not split, but this is unsupported at best and downright dangerous at worst.

+1


source







All Articles