I'm trying to make a MEX function that takes a structure (STRUCT0) and a number of strings (STRING1, STRING2, …) as input arguments. The function should test whether STRUCT0.STRING1.STRING2 is a valid field. The function "checkForFields" below will verify that STRUCT0 is a structure, that STRING1 is a valid field and that STRUCT0.STRING1 is itself a structure. It should then recursively call itself, to check whether STRING2 is a field of STRUCT0.STRING1. However, that's where it goes wrong. When the function recursively calls itself, STRUCT0.STRING1 is no longer recognised as a structure. How should I define the input arguments for the recursive function call?
Many thanks, Dries
#include "mex.h"#include "matrix.h"void checkForFields(mxArray *output[], int nInputArguments, const mxArray *inputArguments[]);void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // define a boolean output argument, initialised to false plhs[0] = mxCreateLogicalScalar(0); // check number of input arguments: if(nrhs<2) { mexErrMsgIdAndTxt("driesMex:fieldExists:nrhs1", "Function requires a structure and at least one field."); } // check number of output arguments: if(nlhs>1) { mexErrMsgIdAndTxt("driesMex:fieldExists:nlhs", "Function supports maximum one output."); } // if first argument is a struct if (mxIsStruct(prhs[0])) { // call a subroutine that will recursively call itself checkForFields(plhs, nrhs, prhs); } else { // first argument is not a struct, issue a warning: mexWarnMsgIdAndTxt("driesMex:fieldExists:firstArg", "First argument is not a structure."); } }void checkForFields(mxArray *output[], int nInputArguments, const mxArray *inputArguments[]){ // *output[]: pointer to output mxArray // nInputArguments: number of input arguments // *inputArguments: pointer to input mxArray, // first argument must be struct, rest are fields to be tested // initialise output to false output[0] = mxCreateLogicalScalar(0); // if first argument is not a struct if (!mxIsStruct(inputArguments[0])) { // issue a warning: mexWarnMsgIdAndTxt("driesMex:fieldExists:checkForFields:firstArg", "CheckForFields: First argument is not a structure."); } // if second argument is a string if (mxIsChar(inputArguments[1])) { // if second argument is a field if (mxGetFieldNumber(inputArguments[0], mxArrayToString(inputArguments[1]))+1) { // output argument should be set to true output[0] = mxCreateLogicalScalar(1); // check if there are more than 2 input arguments if (nInputArguments>2) { // check if second argument is also struct if (mxIsStruct(mxGetField(inputArguments[0], 0, mxArrayToString(inputArguments[1])))){ // recursively call this subroutine checkForFields(output, nInputArguments-1, &inputArguments[1]); // output argument may be overwritten if subsequent field was not a field } } } // else second argument is not a field // output argument was already initialised to false } else { // second argument is not a string, throw error mexErrMsgIdAndTxt("driesMex:fieldExists:nrhs2", "Function requires field argument(s) to be a string."); } }
Best Answer