Recursively build cell array in MEX? c/c++

Hi, before I even attempt to do this, I wanted to ask if anyone else (including Mathworks staff) has tried to recursively build a cell array? I have to deal with a library (hiredis) that may return nested results in a reply struct. I have to examine the reply type, and if it is a certain type, then I have to traverse all the child replies and examine each of them, etc.
Hiredis sets an arbitrary max nesting level, which I am also going to enforce. I set it to 7, which matches hiredis.
My mind is boggling a bit at what might be involved with recursively adding to the cell array which holds all the results. This is the last major task in writing my redis wrapper and I wish I could just ignore this but there are many redis commands which return replies of a type called "Multi Bulk" which can be arbitrarily nested.
I thought it would be better to ask for help in advance instead of posting a bunch of garbage asking "why I get error".
thx George

Réponses (1)

James Tursa
James Tursa le 7 Mar 2013

1 vote

Generally, you can pretty much build and/or examine "nested" cell or struct mxArray variables in the mex environment using the mxSetCell, mxGetCell, mxSetField, mxGetField etc API functions recursively. If you could provide a short descriptive sample (i.e., pseudo-code) of what you are trying to do we can probably advise how to go about it in C/C++.

3 commentaires

George Coles
George Coles le 7 Mar 2013
Modifié(e) : George Coles le 8 Mar 2013
Here is some preliminary code. I am terrible with C, hardly ever do MEX, and am new to Redis, so I am a triple threat.
Edit - here is some code that works to some extent. I am still shaky on memory management and the most elegant way to get data into plhs....
void appendCellArray( mxArray** retVal, int retValRecurseLevel,int recurseMax, redisReply* reply ){
int numChildren;
int elementi;
int replyType;
mwSize dims[2];
if (retValRecurseLevel >= recurseMax){
return;
}
replyType = reply->type;
switch( replyType ){
case REDIS_REPLY_STRING:
{
int index;
unsigned char* output_array_pointer;
int numReplyrows = reply->len;
*retVal = mxCreateNumericMatrix(reply->len, 1, mxUINT8_CLASS, mxREAL);
output_array_pointer = (unsigned char *)mxGetData(*retVal);
for ( index = 0; index < numReplyrows; index++ ) {
output_array_pointer[index] = reply->str[index];
}
}
break;
case REDIS_REPLY_ARRAY:
//cell array to hold results
numChildren = reply->elements;
dims[0] = numChildren;
dims[1] = 1;
*retVal = mxCreateCellArray( 2, &dims[0] );
for( elementi = 0; elementi < numChildren; elementi++ ){
mxArray* childArray;
redisReply* subreply;
subreply = reply->element[elementi];
appendCellArray( &childArray, retValRecurseLevel,recurseMax, subreply );
mxSetCell( *retVal, elementi, childArray );
}
break;
case REDIS_REPLY_INTEGER:
{
*retVal = mxCreateDoubleScalar( reply->integer );
}
break;
case REDIS_REPLY_NIL:
{
const mwSize emptyDims[2] = {0,0};
*retVal = mxCreateNumericArray( 2,emptyDims,mxUINT8_CLASS,mxREAL );
}
break;
case REDIS_REPLY_STATUS:
*retVal = mxCreateString( reply->str );
break;
case REDIS_REPLY_ERROR:
*retVal = mxCreateString( reply->str );
break;
default:
freeReplyObject(reply);
mexErrMsgTxt("we do not know how to deal with this reply type");
}
}
George Coles
George Coles le 18 Mar 2013
no comment on whether I am doing it right?
Jan
Jan le 18 Mar 2013
In general the code looks ok. There are two strong testers on your computer: 1. let the compiler parse the input, 2. let the code run and test the results with your expectations.
Btw., this is not C-code, but C++, because the later allows to declare variables inside the code. But as long as the compiler accept this, this is a cosmethical aspect only.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Write C Functions Callable from MATLAB (MEX Files) dans Centre d'aide et File Exchange

Produits

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by