Path: news.mathworks.com!not-for-mail
From: <HIDDEN>
Newsgroups: comp.soft-sys.matlab
Subject: Re: how to pass cell of 3D matrices to C mex
Date: Fri, 28 Aug 2009 07:04:01 +0000 (UTC)
Organization: Boeing
Lines: 75
Message-ID: <h77vh1$373$1@fred.mathworks.com>
References: <h6tl9j$a0p$1@fred.mathworks.com> <h6tp1k$sja$1@fred.mathworks.com> <h72u3f$5qi$1@fred.mathworks.com> <h73knq$o06$1@fred.mathworks.com> <h74ttb$t3r$1@fred.mathworks.com> <h75bq8$jk6$1@fred.mathworks.com> <h75fld$ort$1@fred.mathworks.com> <h75j0a$rg4$1@fred.mathworks.com> <h75kdb$8c6$1@fred.mathworks.com> <h75tia$ov3$1@fred.mathworks.com> <h7696t$i7u$1@fred.mathworks.com> <h76fi0$213$1@fred.mathworks.com> <h77jke$cl2$1@fred.mathworks.com>
Reply-To: <HIDDEN>
NNTP-Posting-Host: webapp-03-blr.mathworks.com
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1251443041 3299 172.30.248.38 (28 Aug 2009 07:04:01 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Fri, 28 Aug 2009 07:04:01 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 756104
Xref: news.mathworks.com comp.soft-sys.matlab:566678


"Ramana murthy" <omurthy@yahoo.com> wrote in message <h77jke$cl2$1@fred.mathworks.com>...
> Hi James,
> Thank you very much. Now it is working fine.
> Yes, I want to change the contents of the matrices in the mex file. I don't want it as Read only file.
> Though not required for my present application, I wanted to know if the matrices can be of  different sizes. Right now, I see in your code you have restricted to be same size. 

Yes, this can be done with a technique often used in C. Basically, instead of allocating one contiguous block of memory to hold everything, you create an array of double *, each one pointing to a copy of one of your 2D matrices. You allocate the matrix memory on the fly depending on how large the matrix is. It does take a little more clean-up at the end to free all the memory piecemeal, however. e.g.,

#include "mex.h"
#define ARRAYDATA(i,j,k) array[k][i+j*arrayM[k]]
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mxArray *mxcell;
    mwSize i, j, m, n, k, p, numel;
    mwSize *arrayM, *arrayN;
    double *celldata, *arraydata;
    double **array;
    
    (void)plhs; /* unused parameter */

    if( nrhs != 1 ) {
        mexErrMsgTxt("Need exactly one input");
    }
    if( nlhs != 0 ) {
        mexErrMsgTxt("Too many outputs");
    }
    if( !mxIsCell(prhs[0]) ) {
        mexPrintf("Input argument is not cell, it is %s\n",mxGetClassName(prhs[0]));
        mexErrMsgTxt("Returning to MATLAB");
    }
    
    p = mxGetNumberOfElements(prhs[0]);
    array = mxMalloc(p * sizeof(*array));
    arrayM = mxMalloc(p * sizeof(*arrayM));
    arrayN = mxMalloc(p * sizeof(*arrayN));
    
    /* Fill 3D array with input arguments, each a different size */
    for( i=0; i<p; i++){
        mxcell = mxGetCell(prhs[0],i);
        if( !mxIsDouble(mxcell) ) {
            mexPrintf("Input cell is not double, it is %s\n",mxGetClassName(mxcell));
        }
        if( mxIsComplex(mxcell) ) {
            mexErrMsgTxt("Input cell cannot be complex");
        }
        if( mxGetNumberOfDimensions(mxcell) != 2 ) {
            mexErrMsgTxt("Input cell must be 2D");
        }
        celldata = mxGetPr(mxcell);
        arrayM[i] = mxGetM(mxcell);
        arrayN[i] = mxGetN(mxcell);
        numel = mxGetNumberOfElements(mxcell);
        array[i] = mxMalloc(numel * sizeof(**array));
        for( j=0; j<numel; j++ ) {
            array[i][j] = celldata[j]; // copy the data linearly, not as 2D
        }
    }
    for (k=0; k<p; k++) {
        for (j=0; j<arrayN[k]; j++) {
            for(i=0; i<arrayM[k]; i++) {
                mexPrintf("array(%d,%d,%d) = %g \n", i+1, j+1, k+1, ARRAYDATA(i,j,k));
            }
        }
    }
    // other code to use array here
    // free up the allocated memory when done
    for( k=0; k<p; k++ ) {
        mxFree(array[k]);
    }
    mxFree(array);
    mxFree(arrayM);
    mxFree(arrayN);
}

James Tursa