How to access MatDoub in a structure?


John Knowles
11-14-2013, 08:14 AM
I am new to both C++ and NR3. The code below created a structure from a Matlab structure. Using member functions, I can access some bits of the structure but not the MatDoub variables (they always appear empty) . What am I missing here? How can I access MatDoub objects in a structure?

1)In my gateway function, all seems to work fine, creating a ChebyDatStruct instance called ChebyStruct.:

ChebyDatStruct ChebyStruct(prhs[3]);

2)The workhorse member function is then called:
ChebyStruct.ComputeCoef(ExpVal,Params,FlagVec,flag );
3)here's the relevant excerpt of the member function
void ChebyDatStruct::ComputeCoef(VecDoub ExpVal,Parameters Params,FlagStruct FlagVec,int flag)
{
printf("ComputeCoeff 0000 StateList =[%d %d]\n",StateList.nrows(),StateList.ncols());
}
The result is zeros, and StateList is clearly an unitianalized object as the program crashes when I try to access its elements.
ComputeCoeff 0000 StateList =[0 0]
On the other hand if use the member funciton
FieldInfo("StateList",InfoStateList), I get the right information, but this is from using mx functions to directly access the ChebyMx variable in the structure
mx=mxGetField(ChebyMx,0, fname);
ndims = mxGetNumberOfDimensions(mx);
result:
ComputeCoeff 0000 StateList rows=196 cols=3


Here's the structure definition, then the constructor.
struct ChebyDatStruct
{
//public:
//--------------------------------
//variables
int ifield, nfields;
mwSize NStructElems;
mwSize ndim;
MatDoub StateList,Imat,Jmat,Pts_id_lambda,PointList,ChebyC oef,ChebPoly2DMat,ChebORD,PolyList,Basis;
//--------------------------------
//constructor functions
ChebyDatStruct();
ChebyDatStruct(mxArray const *mx);
//--------------------------------
//utilities
void MakeChebyDatStruct(mxArray *mx);
void FieldInfo(const char *fname,VecInt_O &InfoVec);
void ReadInt(const char *fname,MatInt_O Output);
void ReadDoub(const char *fname,MatDoub_O Output);
void ShowFields();
//--------------------------------
//the real work
void ComputeCoef(VecDoub ExpVal,Parameters Params,FlagStruct FlagVec,int flag);
Doub ValApprox(Mat3DDoub NRstate3D,VecDoub ExpVal,Parameters Params,VecDoub ValFit,FlagStruct FlagVec,int flag);
//--------------------------------
private:
mxArray *ChebyMx;
char **fnames; /* pointers to field names */
//mxArray *ChebyStruct;//access to data only via public functions above
int nstate;
} ;

ChebyDatStruct::ChebyDatStruct(mxArray const *mx)
{
if(!mxIsStruct(mx))
mexErrMsgIdAndTxt( "MATLAB:ChebyDatStruct:inputNotStruct",
"mx must be a structure x1.");
const mwSize *dim_array;
nfields = mxGetNumberOfFields(mx);
fnames = (char **)mxCalloc(nfields, sizeof(*fnames));
/* get field name pointers */
for (ifield=0; ifield< nfields; ifield++)
{
fnames[ifield] = (char *)mxGetFieldNameByNumber(mx,ifield);
}
ChebyMx=(mxArray *)mx;
MatDoub StateList(mxGetField(ChebyMx,0, "StateList"));
MatDoub Imat(mxGetField(ChebyMx,0, "Imat"));
MatDoub Jmat(mxGetField(ChebyMx,0, "Jmat"));
MatDoub Pts_id_lambda(mxGetField(ChebyMx,0, "Pts_id_lambda"));
MatDoub PointList(mxGetField(ChebyMx,0, "PointList"));
MatDoub ChebPoly2DMat(mxGetField(ChebyMx,0, "ChebPoly2DMat"));
MatDoub ChebORD(mxGetField(ChebyMx,0, "ChebORD"));
MatDoub PolyList(mxGetField(ChebyMx,0, "PolyList"));
MatDoub Basis(mxGetField(ChebyMx,0, "Basis"));
mexPrintf("ChebyDatStruct: StateList has dimensions %d %d\n",StateList.nrows(),StateList.ncols());
mexPrintf("ChebyDatStruct: PolyList has dimensions %d %d\n",PolyList.nrows(),PolyList.ncols());

}

John Knowles
11-24-2013, 03:23 AM
The problem is very basic : how to create public data members using VecDoub, MatDoub etc.

The example below is quite simple and demonstrates the asymmetry between creating a VecDoub member and a static array. The issue seems to be that the VecDoub object is destroyed once the structure is constructed, whereas I want to be accessible from outside the structure, as the array and other POD objects are.

Of course in the end I could just use the array and bind a VecDoub to it every time I want to use it. But in the end I want to use 3-D arrays (Mat3DDoub) and binding becomes more complicated. Also I may have many public data members to deal with.

J
#include "nr3matlab.h"
#include "mex.h"
#include "matrix.h"
struct Parameters
{
public:
//variables
double df ,dlt1,dlt2;
VecDoub *dltVD;
double dlt[2];
//constructor functions
Parameters();
Parameters(mxArray const *mx){MakeParams(mx);}
//utilities
void MakeParams(mxArray const *mx);
private:
double *Params_Pr;
} ;

void Parameters::MakeParams(mxArray const *mx)
{
double *Params_Pr = mxGetPr(mx)-1 ;
//--------------------------------------
// Read parameters
//--------------------------------------
df = *(Params_Pr +1) ;

VecDoub dltVD(2,*(Params_Pr +2) );
dlt[0]= *(Params_Pr +2) ;
dlt[1]= *(Params_Pr +3) ;
printf("MakeParams dlt Address=%d dlt=[%f %f] Address=%d dltVD=[%f %f]\n",&dlt ,dlt[0],dlt[1],&dltVD ,dltVD[0],dltVD[1]);
}
/*
--------------------------------------
Gateway function to matlab
type in Matlab:
>>Params=[0.96,0.2,0.6]
>>TestParams(Params)
--------------------------------------
*/
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
const mwSize *dim_array;
mxArray const *mxTemp;
Parameters Params(prhs[0]);
printf("Back in Gateway Params.df=%f Params.dlt Address=%d Params.dltVD Address=%d \n", Params.df,Params.dlt, &Params.dltVD);
printf("dlt=[%f %f] dltVD=[%f %f]\n",&Params.dlt[0],&Params.dlt[1] ,&Params.dltVD[0],&Params.dltVD[1]);
}
/*
matlab output
>> TestParams(Params)
MakeParams dlt Address=296100176 dlt=[0.200000 0.600000] Address=296099040 dltVD=[0.200000 0.200000]
Back in Gateway Params.df=0.960000 Params.dlt Address=296100176 Params.dltVD Address=296100168
dlt=[0.960000 0.000000] dltVD=[0.000000 0.000000]

*/