In mex file, I can't overwrite scalar value through the pointer in matlab2016a, although I can overwrite the scalar value through the pointer in matlab2013a and I can also overwrite the array through the pointer in matlab2016a.
2 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
c0maru
am 7 Okt. 2016
Kommentiert: c0maru
am 9 Okt. 2016
[environment]
OS: OSX10.11 and maxOS Sierra(10.12)
MATLAB: matlab2013a and matlab2016a
Xcode: xcode7 and xcode8
------------------------------------------------------
In my work, I must use the following mex file in the old package.
//destructiveMatrixWriteAtIndices.c
//------------------------------------------------------
#include <matrix.h> /* Matlab matrices */
#include <mex.h>
#include <stddef.h> /* NULL */
#define notDblMtx(it) (!mxIsNumeric(it) || !mxIsDouble(it) || mxIsSparse(it) || mxIsComplex(it))
void mexFunction(int nlhs, /* Num return vals on lhs */
mxArray *plhs[], /* Matrices on lhs */
int nrhs, /* Num args on rhs */
const mxArray *prhs[] /* Matrices on rhs */
)
{
double *mtx;
double *newValues;
double *doubleStartIndex;
int i, startIndex, size;
mxArray *arg;
if (nrhs != 3) mexErrMsgTxt("requires 3 arguments.");
/* ARG 1: MATRIX */
arg = prhs[0];
if notDblMtx(arg) mexErrMsgTxt("MTX arg must be a real non-sparse matrix.");
mtx = mxGetPr(arg);
arg = prhs[1];
if notDblMtx(arg) mexErrMsgTxt("MTX arg must be a real non-sparse matrix.");
newValues = mxGetPr(arg);
size = (int) mxGetM(arg) * mxGetN(arg);
arg = prhs[2];
if notDblMtx(arg) mexErrMsgTxt("MTX arg must be a real non-sparse matrix.");
doubleStartIndex = mxGetPr(arg);
startIndex = (int) doubleStartIndex[0];
for (i=0; i<size; i++)
{
mtx[i+startIndex] = newValues[i];
}
return;
}
//------------------------------------------------------
This mex file is the function to overwrite the scalar and the part of matrix through the pointer.
e.g. in matlab2013a command window (scalar in matlab2013a)
a = 1;
destructiveMatrixWriteAtIndices(a, 3, 0);
and the variable "a" becomes "3".
e.g. in matlab2013a and matlab2016a command window (matrix in matlab2013a and matlab2016a)
a = [1, 2];
destructiveMatrixWriteAtIndices(a, 3, 0);
and the variable "a" becomes "[3, 2]".
e.g. in matlab2016a command window (scalar in matlab2016a)
a = 1;
destructiveMatrixWriteAtIndices(a, 3, 0);
and the variable "a" becomes "1"! Why?
I also used the lldb, and revealed the strange behavior of this code.
In matlab2013a and matlab2016a, when I run the following snippet.
a = 1;
destructiveMatrixWriteAtIndices(a, 3, 0);
The lldb revealed "*mtx = 3" at the end of the mex function in both matlab, but the mex function couldn't pass the result(*mtx = 3, or prhs[0] = 3) through the pointer in the only matlab2016a.
It's very strange behavior!
※I have understood that this mex function is very danger, but this mex function was used at some points in the package that I must use. Therefore, I must fix this mex file and make the package run in matlab2016a.
Please help me.
2 Kommentare
James Tursa
am 7 Okt. 2016
Did you recompile this mex routine under R2016a? Or are you using the mex routine you compiled in an earlier version? I would try recompiling if you haven't yet. I would also put this statement at the end of your mex routine to verify that the double data did in fact get changed in the mex routine:
mexCallMATLAB(0,NULL,1,prhs,"disp");
What is the purpose of this mex routine? I.e., why can't you just do a regular indexed assignment at the m-file level to accomplish this? Are you trying to force in-place data replacement even if the variable is a shared-data-copy of another variable? Or what?
Akzeptierte Antwort
Philip Borghesani
am 7 Okt. 2016
Scalar values no longer (as of R2015b) create mxarrays by default. They are created as needed when a mex or buit-in function is called. Run the following code as a script (or function) after calling format debug.
%script t1
a=5;
a
a
% end script
>> t1
a =
Structure address = 61963510
m = 1
n = 1
pr = aa4a51c0
pi = 0
5
a =
Structure address = 61963510
m = 1
n = 1
pr = f93815a0
pi = 0
5
Note that the pr values are different. The mex file is modifying a copy of the scalar value that is used by the MATLAB code.
1 Kommentar
James Tursa
am 7 Okt. 2016
Bearbeitet: James Tursa
am 7 Okt. 2016
Wow ... that's interesting. The mxArray structure is the same but the data area is created on the fly for each use from some other behind-the-scenes source that you can't get at. What was the reason for this change? Some minor performance boost? Avoiding shared data copies of scalars? Or ...?
"Scalar values no longer (as of R2015b) create mxarrays by default."
Can you elaborate? Looks like the mxArray is in fact created for the scalar since the mxArray structure address is constant. It appears to me that only the data area is created on the fly (I presume to avoid shared data copies of scalars or some other very minor performance boost reason).
Weitere Antworten (1)
James Tursa
am 7 Okt. 2016
One possibility is that MATLAB is not passing "a", but a copy of "a" to the mex routine. In my experience MATLAB always has passed the actual variables to the mex routine, but maybe this has changed and now MATLAB passes a temporary copy of scalars. Do the following to make sure you are getting the original "a" passed to the mex routine:
format debug
a = 1;
destructiveMatrixWriteAtIndices(a, 3, 0);
Then in the mex routine print out the address of prhs[0], e.g.,
mexPrintf("prhs[0] = %p\n",prhs[0]);
and compare this to the variable structure address that is printed out at the m-file level. They should be the same, but maybe in R2016a they aren't for some reason. Let me know what you find out. This would be a real bummer if the argument passing mechanism for mex files has changed!
1 Kommentar
Siehe auch
Kategorien
Mehr zu Whos finden Sie in Help Center und File Exchange
Produkte
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!