Path: news.mathworks.com!newsfeed-00.mathworks.com!newsfeed2.dallas1.level3.net!news.level3.com!postnews.google.com!news2.google.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!cyclone1.gnilink.net!spamkiller2.gnilink.net!gnilink.net!trndny07.POSTED!702e7bde!not-for-mail
From: James Tursa <aclassyguywithaknotac@hotmail.com>
Newsgroups: comp.soft-sys.matlab
Subject: Re: Pass structure to MATLAB
Message-ID: <6p9li3t0t4mc554emmf7q74rd5iut85d5l@4ax.com>
References: <fgb6fp$8rt$1@fred.mathworks.com>
X-Newsreader: Forte Agent 3.3/32.846
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Lines: 243
Date: Fri, 02 Nov 2007 04:35:34 GMT
NNTP-Posting-Host: 71.112.28.167
X-Complaints-To: abuse@verizon.net
X-Trace: trndny07 1193978134 71.112.28.167 (Fri, 02 Nov 2007 00:35:34 EDT)
NNTP-Posting-Date: Fri, 02 Nov 2007 00:35:34 EDT
X-Original-Bytes: 8179
Xref: news.mathworks.com comp.soft-sys.matlab:435762


On Thu, 1 Nov 2007 00:26:33 +0000 (UTC), "Faisal "
<faisal_mufti.nospam@yahoo.com> wrote:

>Hi I have the following structure in C++. I am reading a
>file and at the end of each loop I want to pass my structure
>to MATLAB with mex fucntion. Any help please ?
>
>struct Frame
>{
>     double frame_no;
>     double dist[3072];
>     double ampl[3072];
>};
>
>struct UShortFrame
>{
>     unsigned frame_no;
>     unsigned short dist[3072];
>     unsigned short ampl[3072];
>      
>};
>
>void ReadFromFile(const char *filename, int ArraySize)
>{
>      
>      int i;unsigned read_frame_no;
>      UShortFrame* usframe = new UShortFrame;
>
>      ifstream filein(filename, ios::in | ios::binary);
>      if(!filein) {  
>            std::cout << "Cannot open file to read.\n"; }
>           if (filein.read((char*)usframe, 
>sizeof(UShortFrame)))
>             {
>               Frame* frame = new Frame;
>               frame->frame_no = usframe->frame_no;
>                for (int i = 0; i < 3072; ++i)
>               {
>                   frame->dist[i] = usframe->dist[i];
>                   frame->ampl[i] = usframe->ampl[i];
>
>               }    
>                  
>             }
>            filein.close();
>            delete []usframe;
>	  // cout<<(*frame).dist[0]<<endl;    
>          // pass frame structure to MATLAB
>            
> }


 
Here is a complete working mex file that puts Frame and UShortFrame
structures into the MATLAB base workspace. mPut1 and mPut2 could
possibly be optimized a bit, but you get the idea. There are a few
points to note about this mex file:

1) I knew for this example that the ARRAYSIZE was 3072, so I didn't
bother to check that sizeof(double)*ARRAYSIZE and sizeof(unsigned
short)*ARRAYSIZE did not overflow a size_t. For more robust code one
would check this result before using it.

2) I didn't bother to check the return values from
mxCreateStructMatrix and mxCreateNumericMatrix to see that they
completed ok because this was a mex file. For mex files, if they don't
complete ok then they will not return at all ... MATLAB will simply
clean up allocated memory it knows about and exit and return control
back to MATLAB. If you use this code in an engine application then you
*will* have to put in code to check for valid return values.

3) I used the mxCalloc function to create new structure variables
instead of using the C++ "new" operator for two reasons. First, this
lets people use this example using the built-in lcc compiler in case
they don't have a supported C++ compiler. Second, (and I am not at all
sure about this one), I don't think the  MATLAB memory manager knows
anything about any memory you allocated with the "new" operator. So if
anything goes wrong with any of the mxCreate... or mxCalloc routines
and the mex file exits back to MATLAB, all of the memory associated
with any mxCreate... or mxCalloc calls will get freed, but your
allocated variables created with the "new" operator may not get
deleted. This would be a potential source for a memory leak. (Can
anyone out there in the MATLAB community who knows more about this
confirm what happens in this case? I need help here.)

4) Creating the structure variables using mxCalloc was relative simple
in this case because the structure was straightforward. The example
would be more complex if your structure had pointers that pointed to
other allocated memory, etc. And freeing this memory with mxFree for
these cases would also be more complex ... would need to free the low
levels first, etc. After having said this, I will point out that the
MATLAB memory manager will save you and free all memory you allocated
with the mxCreate... and mxCalloc calls when the mex file exits, even
if you forget to do it.

James Tursa


#include "mex.h"
#include "matrix.h"
#include <stdlib.h>
#include <string.h>
 
#define ARRAYSIZE 3072
 
#ifndef mwSize
#define mwSize int
#endif
 
#ifndef mwIndex
#define mwIndex int
#endif
 
struct Frame
{
     double frame_no;
     double dist[ARRAYSIZE];
     double ampl[ARRAYSIZE];
};
 
struct UShortFrame
{
     unsigned frame_no;
     unsigned short dist[ARRAYSIZE];
     unsigned short ampl[ARRAYSIZE];
};
 
int mPut1(struct Frame *f, char name[]);
int mPut2(struct UShortFrame *u, char name[]);
 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, 
     const mxArray *prhs[])
{
    struct Frame *f;
    struct UShortFrame *u;
    size_t t1 = 1;
    int i;
    
    f = (struct Frame *) mxCalloc( t1, sizeof(struct Frame) );
    f->frame_no = 1.0;
    for( i=0; i<ARRAYSIZE; i++ )
    {
        f->dist[i] = (double) i;
        f->ampl[i] = (double) 2*i;
    }
    
    u = (struct UShortFrame *) mxCalloc( t1, sizeof(struct
UShortFrame) );
    u->frame_no = 1;
    for( i=0; i<ARRAYSIZE; i++ )
    {
        u->dist[i] = i;
        u->ampl[i] = 2*i;
    }
    
    if( mPut1(f, "f") )
        mexPrintf("mPut1 for f did not work\n");
    
    if( mPut2(u, "u") )
        mexPrintf("mPut2 for u did not work\n");
    
    mxFree(f);
    mxFree(u);
}
 
// Put a Frame structure into MATLAB base workspace
 
int mPut1(struct Frame *f, char name[])
{
    mxArray *pm, *mx;
    mwSize m, n;
    const int nfields = 3;
    const char *fieldnames[3] = {"frame_no","dist","ampl"};
    const mwIndex index = 0;
    int r;
    
    m = 1;
    n = 1;
    pm = mxCreateStructMatrix(m, n, nfields, fieldnames);
    
    m = 1;
    n = 1;
    mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);
    memcpy(mxGetPr(mx), &(f->frame_no), sizeof(double));
    mxSetFieldByNumber(pm, index, 0, mx);
    
    m = 1;
    n = ARRAYSIZE;
    mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);
    memcpy(mxGetPr(mx), (f->dist), sizeof(double)*ARRAYSIZE);
    mxSetFieldByNumber(pm, index, 1, mx);
    
    m = 1;
    n = ARRAYSIZE;
    mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);
    memcpy(mxGetPr(mx), (f->ampl), sizeof(double)*ARRAYSIZE);
    mxSetFieldByNumber(pm, index, 2, mx);
    
    r = mexPutVariable("base", name, pm);
    mxDestroyArray(pm);
    
    return r;
}
 
// Put a UShortFrame structure into MATLAB base workspace
 
int mPut2(struct UShortFrame *u, char name[])
{
    mxArray *pm, *mx;
    mwSize m, n;
    const int nfields = 3;
    const char *fieldnames[3] = {"frame_no","dist","ampl"};
    const mwIndex index = 0;
    int r;
    
    m = 1;
    n = 1;
    pm = mxCreateStructMatrix(m, n, nfields, fieldnames);
    
    m = 1;
    n = 1;
    mx = mxCreateNumericMatrix(m, n, mxUINT16_CLASS, mxREAL);
    memcpy(mxGetPr(mx), &(u->frame_no), sizeof(unsigned short));
    mxSetFieldByNumber(pm, index, 0, mx);
    
    m = 1;
    n = ARRAYSIZE;
    mx = mxCreateNumericMatrix(m, n, mxUINT16_CLASS, mxREAL);
    memcpy(mxGetPr(mx), (u->dist), sizeof(unsigned short)*ARRAYSIZE);
    mxSetFieldByNumber(pm, index, 1, mx);
    
    m = 1;
    n = ARRAYSIZE;
    mx = mxCreateNumericMatrix(m, n, mxUINT16_CLASS, mxREAL);
    memcpy(mxGetPr(mx), (u->ampl), sizeof(unsigned short)*ARRAYSIZE);
    mxSetFieldByNumber(pm, index, 2, mx);
    
    r = mexPutVariable("base", name, pm);
    mxDestroyArray(pm);
    
    return r;
}