How does MATLAB deal with this?
MATLAB: Can MATLAB pass by reference
functionsMATLABmatlab objectsmatlab oopooppassbyreference
Related Solutions
You don't have enough information available (officially) to do what you are trying to do reliably and safely in a mex routine. The reason is that many MATLAB operations (such as assignments) are, by default, shared data copies of each other. That is, the data pointers point to the same memory. Data copies are only made when the data of one copy changes. E.g., consider this
>> format debug>> X = 1:3X =Structure address = 7711b40m = 1n = 3pr = 32bd2680pi = 0 1 2 3>> Y = XY =Structure address = 7712780m = 1n = 3pr = 32bd2680pi = 0 1 2 3>> Y(1) = -1Y =Structure address = 7712780m = 1n = 3pr = 32bd2900pi = 0 -1 2 3
When X is first created, the real data pointer pr points to memory location 32bd2680. At this point you could safely modify this variable in-place in a mex routine with no ill side effects since it isn't sharing data with any other variable. But after the assignment Y = X is made, notice that the real data pointer pr for Y is the same as the real data pointer for X, namely that 32bd2680 address again. Now you have a problem if you try to modify X in-place in a mex routine since any changes will happen to the Y variable as well. Then when you change the first element of Y notice that its real data pointer pr has changed to a new address 32bd2900. Now X and Y are not sharing data pointers anymore and you could safely modify X in-place in a mex routine with no ill side effects.
The problem with all of this is that there are NO OFFICIAL API FUNCTIONS to tell you, in a mex routine, when a variable is sharing data with another variable. And in fact, this is not the only way that variables can be sharing. There could be reference copies around (i.e., field or cell elements), and there could be parent copies around (the struct or cell that the variable is part of could be shared with another variable). NONE of this is visible to you in mex routines with any of the official API functions. So even if you could detect how your mex routine was called (new = myfunc(origin) vs origin = myfunc(origin)), you could never be sure that in the origin = myfunc(origin) case it would be safe to modify origin in-place inside the mex routine.
The only way to detect this sharing condition in a mex routine is to hack into the mxArray structure itself and look at the CrossLink and Reference Count fields to see if they are not NULL or 0. And if the variable happens to be a SUB-ELEMENT (cell element or field of a struct) then it can get VERY complicated and messy to try and figure out if there is any parent sharing involved.
The only practical solution I can offer you is to manage, at your m-file calling level, your variable such that data-sharing NEVER takes place. I.e., never do anything (such as a simple assignment to another variable) that could cause data sharing to take place. Then call your mex function in one of two ways:
1) new = myfunc(origin) 2) myfunc(origin)
In method 1, you simply check nlhs to see that it is 1 ... and that is your clue to the mex routine to NOT modify the variable in-place, but rather create a new output variable.
In method 2, you simply check nlhs to see that it is 0 ... and that is your clue to the mex routine that it is directed to modify the variable in-place. The burden to make sure there are no ill side effects is entirely on you at the m-file level to make sure you didn't do anything that would cause data sharing.
Note that I am not advising you to take this approach ... I am simply pointing out what I think to be the only practical way of accomplishing your objective should you really need to modify variables in-place in a mex routine. Bottom line is you need to understand what operations at the m-file level cause data sharing, and avoid those operations with the variable you want to modify in-place.
The address of a MATLAB variable can be obtained using a MEX function.
The gateway routine of a MEX function has the following signature:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
Here prhs is an array of right-hand input arguments. It is an array of pointers to type mxArray. When a variable is passed as an input argument to a MEX function, the pointer to that variable is copied into prhs.
For example, if a MEX function, 'myMexFunction', is called using one input argument as shown below:
a = 5;myMexFunction(a);
the address of the variable 'a' is copied into prhs[0].
The following C-MEX function, "mem_address.c", illustrates how you can obtain the address of each element of a row vector of type double. This code can be expanded to operate on other data-types as well.
#include "mex.h"void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ double *ptr; int i; mwSize n; /* Function accepts only one input argument */ if(nrhs > 1) { mexErrMsgTxt("Only one input argument accepted\n\n"); } /* This function works only with row vectors */ if( mxGetM(prhs[0]) > 1 ) { mexErrMsgTxt("Only row vectors are accepted\n\n"); } /* Get the Pointer to the Real Part of the mxArray */ ptr = mxGetPr(prhs[0]); n = mxGetN(prhs[0]); mexPrintf("Pointer Address of mxArray = %x\n\n", prhs[0]); for(i = 0; i < n; i++) { mexPrintf("Value of Real Argument at array index %d = %f\n", i, ptr[i]); mexPrintf("Pointer Address = %x\n\n", &ptr[i]); } }
You can MEX this C-file using the following command at the MATLAB prompt:
mex mem_address.c
This will generate a MEX file with an extension depending on your platform. You can run this MEX file as follows:
a = 5;mem_address(a);
For more information about MEX-files please refer to the following:
Best Answer