简体   繁体   中英

MATLAB's mxGetFieldByNumber and mxGetFieldNameByNumber return incongruent results

I have a C mex routine that is iterating over subfields of a structure. Sometimes calling mxGetFieldByNumber() returns NULL when mxGetFieldNameByNumber() returns a string for the same field idx. Here is a toy:

numFields = getNumberOfFields( currentField );
for( fieldIdx = 0; fieldIdx < numFields; fieldIdx ++){
subField = mxGetFieldByNumber( currentField, 0 , fieldIdx );
fieldName = mxGetFieldNameByNumber(currentField, fieldIdx );
}

I have read through the documentation of both functions. A NULL can be returned if (in this example) currentField were not a mxArray which I know is not the case because mxGetFieldNameByNumber() returns something sensible. Insufficient heap space could be the problem but I've checked that and it is on 400kb. NULL can also be returned when no value is assigned to the specified field but I've looked and it appears the value is zero.

Any thoughts?

When a struct is created at the MATLAB level or in a mex routine via mxCreateStruct, not all field elements are necessarily populated. In such case, MATLAB physically stores a NULL pointer (ie, 0) in those data spots (a struct is essentially an array of mxArray pointers). Eg, take the following code snippet assuming X doesn't exist yet:

X.a = 5;
X(2).b = 7;

The X struct variable actually has four elements, namely X(1).a, X(1).b, X(2).a, and X(2).b. But you only set two of these elements. What does MATLAB do with the other elements? Answer: It simply stores NULL pointers for those spots. If you subsequently access those NULL spots in your MATLAB code, MATLAB will simply create an empty double matrix on the fly.

At the mex level, a similar thing happens. When you first create the struct with mxCreateStruct, MATLAB simply fills all of the element spots with NULL values. Then you can populate them in your code if you want, but note that leaving them as NULL is perfectly acceptable for returning back to MATLAB. The routine mxGetFieldByNumber actually gets the element mxArray pointer, and mxGetFieldNameByNumber gets the name of the field itself ... two very different things. If you get a NULL result from a valid mxGetFieldByNumber call (ie your index is not out of range), that simply means this element was never set to anything. You should never get a NULL result from a valid mxGetFieldNameByNumber call, since all field names are required to exist.

If you were to pass in the X created above to a mex routine and then examine prhs[0] you would find the following:

mxGetFieldByNumber(prhs[0],0,0)
returns a pointer to an mxArray that is the scalar double 5
mxGetFieldByNumber(prhs[0],0,1)
returns a NULL pointer
mxGetFieldByNumber(prhs[0],1,0)
returns a NULL pointer
mxGetFieldByNumber(prhs[0],1,1)
returns a pointer to an mxArray that is the scalar double 7
mxGetFieldNameByNumber(prhs[0],0)
returns a pointer to the string "a"
mxGetFieldNameByNumber(prhs[0],1)
returns a pointer to the string "b"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM