From: Samuel on
Hello !

I am trying to optimize a clustering algorithm using MEX/cpp. It is the first time that I use mex, but I have done some cpp and some matlab before.

Here is the problem : while in cpp file, I want to use the mexCallMATLAB function in order to use built in function such as inv() and det(). I can get the code to compile and transfer arrays of the correct size, but the arrays seems to be empty (zeros) :

Here's the code, if anyone can finds the trouble, or direct me to information (I have looked a lot but have not find the same problem in other topics) it would be really appreciated, I have looked at it a lot and do not know what to do:
/******************************************************/
// The mex file :
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

//declare variables
mxArray *k_m, *tab_m, *muInit_m, *maxIter_m, *mask_m, *mu_m, *covMat_m, *prop_m;
const int *dims;
double *tab, *muInit, *mu, *prop, *covMat;
int k, maxIter,*mask;
int nbPixTot, nb, numdims;
int i,j;

//associate inputs
k_m = mxDuplicateArray(prhs[0]);
tab_m = mxDuplicateArray(prhs[1]);
muInit_m = mxDuplicateArray(prhs[2]);
maxIter_m = mxDuplicateArray(prhs[3]);

//figure out dimensions
dims = mxGetDimensions(prhs[1]);
numdims = mxGetNumberOfDimensions(prhs[1]);
nb = (int)dims[1];
nbPixTot = (int)dims[0];

//associate pointers input
k = (int)mxGetScalar(k_m);
tab = mxGetPr(tab_m);
muInit = mxGetPr(muInit_m);
maxIter = (int)mxGetScalar(maxIter_m);

//associate outputs
mask_m = plhs[0] = mxCreateNumericMatrix(nbPixTot,1, mxINT32_CLASS, mxREAL);
mu_m = plhs[1] = mxCreateDoubleMatrix(k,nb,mxREAL);
covMat_m = plhs[2] = mxCreateDoubleMatrix(k,nb*nb,mxREAL);
prop_m = plhs[3] = mxCreateDoubleMatrix(k,1,mxREAL);

//associate pointers output
mask = (int*) mxGetData(mask_m);
mu = mxGetPr(mu_m);
covMat = mxGetPr(covMat_m);
prop = mxGetPr(prop_m);

// calculate different things:
calcMask(mask, tab, muInit, k, nb, nbPixTot);
calcProp(mask, prop,k, nbPixTot);
calcCovMat(covMat, tab, muInit, mask, k,nbPixTot, nb);

....


/*************************************************************/
mxArray *sortie[2];

// Should I initialize my output mxArray ?
sortie[1] = mxCreateDoubleMatrix(k, nb*nb, mxREAL);
sortie[2] = mxCreateDoubleMatrix(k, 1, mxREAL);
/* double *invCovMatP = mxGetPr(sortie[1]);
double *detCovMatP = mxGetPr(sortie[2]);
*/
// With that line, the input is ok, but the output is only zeros
mexCallMATLAB(2, sortie, 1, &plhs[2], "invAndDet");
/* But, I don't understant why that line is not equivalent :
mexCallMATLAB(2, sortie, 1, &covMat_m, "invAndDet");
*/
// Should I do that before or after the mexCallMATLAB
double *invCovMatP = mxGetPr(sortie[1]);
double *detCovMatP = mxGetPr(sortie[2]);



for (int i =0; i<k ; i++)
{
mexPrintf("detMat : %f\n", detCovMatP[i]);
}

return;
}
/****************************************************/


// The m file I am trying to use :

function [inverseMatrix detOfMatrix] = invAndDet(covMat);

[k, nb] = size(covMat);
nb =sqrt(nb);

inverseMatrix = 0*covMat;
detOfMatrix = zeros(k,1);

for i = 1:k
matrixTemp = reshape(covMat(i,:),nb,nb);
invTemp = inv(matrixTemp);
inverseMatrix(i,:) = reshape(invTemp,1,nb*nb);
detOfMatrix(i) = det(matrixTemp);
end;

return;

/*******************************************************/

Having used the debugger, I know that the results are not zeros inside the m-file, but it looks like I can't get them back in the cpp file. It might have to do with pointers since I have not used them often yet.


Thanks to anyone that could help me or give me a link with some information !

Samuel
From: James Tursa on
"Samuel " <sam030(a)gmail.com> wrote in message <i1lt8d$3gk$1(a)fred.mathworks.com>...
>
> /*************************************************************/
> mxArray *sortie[2];
>
> // Should I initialize my output mxArray ?
> sortie[1] = mxCreateDoubleMatrix(k, nb*nb, mxREAL);
> sortie[2] = mxCreateDoubleMatrix(k, 1, mxREAL);
> /* double *invCovMatP = mxGetPr(sortie[1]);
> double *detCovMatP = mxGetPr(sortie[2]);

No. You should not initialize the sortie array. Doing so simply creates a memory leak since the downstream mexCallMATLAB will wipe out the contents of sortie and you will lose your pointers to the mxArrays you just created. Besides, you are using the wrong indexing anyway (should be [0] and [1], not [1] and [2]).

> double *invCovMatP = mxGetPr(sortie[1]);
> double *detCovMatP = mxGetPr(sortie[2]);

Wrong indexing again. Should be [0] and [1], not [1] and [2]. I'm surprised you didn't crash MATLAB since you are corrupting memory.

I haven't had time to look at the rest of your code in detail yet. But at least you can fix this up right away.

James Tursa
From: Samuel on
"James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <i1m6eo$l51$1(a)fred.mathworks.com>...
> "Samuel " <sam030(a)gmail.com> wrote in message <i1lt8d$3gk$1(a)fred.mathworks.com>...
> >
> > /*************************************************************/
> > mxArray *sortie[2];
> >
> > // Should I initialize my output mxArray ?
> > sortie[1] = mxCreateDoubleMatrix(k, nb*nb, mxREAL);
> > sortie[2] = mxCreateDoubleMatrix(k, 1, mxREAL);
> > /* double *invCovMatP = mxGetPr(sortie[1]);
> > double *detCovMatP = mxGetPr(sortie[2]);
>
> No. You should not initialize the sortie array. Doing so simply creates a memory leak since the downstream mexCallMATLAB will wipe out the contents of sortie and you will lose your pointers to the mxArrays you just created. Besides, you are using the wrong indexing anyway (should be [0] and [1], not [1] and [2]).
>
> > double *invCovMatP = mxGetPr(sortie[1]);
> > double *detCovMatP = mxGetPr(sortie[2]);
>
> Wrong indexing again. Should be [0] and [1], not [1] and [2]. I'm surprised you didn't crash MATLAB since you are corrupting memory.
>
> I haven't had time to look at the rest of your code in detail yet. But at least you can fix this up right away.
>
> James Tursa


Thank you for your time.

Of course you are right about the indexing ! Having done only matlab programming in the last two months or so I tried to be careful about indexing, but I did not catch this mistake.

I will look again with this mistake corrected and see if things work now. I'll give you feedback once it is done.

Thanks again,

Samuel
From: Samuel on
"Samuel " <sam030(a)gmail.com> wrote in message <i1mok8$rv$1(a)fred.mathworks.com>...
> "James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <i1m6eo$l51$1(a)fred.mathworks.com>...
> > "Samuel " <sam030(a)gmail.com> wrote in message <i1lt8d$3gk$1(a)fred.mathworks.com>...
> > >
> > > /*************************************************************/
> > > mxArray *sortie[2];
> > >
> > > // Should I initialize my output mxArray ?
> > > sortie[1] = mxCreateDoubleMatrix(k, nb*nb, mxREAL);
> > > sortie[2] = mxCreateDoubleMatrix(k, 1, mxREAL);
> > > /* double *invCovMatP = mxGetPr(sortie[1]);
> > > double *detCovMatP = mxGetPr(sortie[2]);
> >
> > No. You should not initialize the sortie array. Doing so simply creates a memory leak since the downstream mexCallMATLAB will wipe out the contents of sortie and you will lose your pointers to the mxArrays you just created. Besides, you are using the wrong indexing anyway (should be [0] and [1], not [1] and [2]).
> >
> > > double *invCovMatP = mxGetPr(sortie[1]);
> > > double *detCovMatP = mxGetPr(sortie[2]);
> >
> > Wrong indexing again. Should be [0] and [1], not [1] and [2]. I'm surprised you didn't crash MATLAB since you are corrupting memory.
> >
> > I haven't had time to look at the rest of your code in detail yet. But at least you can fix this up right away.
> >
> > James Tursa
>
>
> Thank you for your time.
>
> Of course you are right about the indexing ! Having done only matlab programming in the last two months or so I tried to be careful about indexing, but I did not catch this mistake.
>
> I will look again with this mistake corrected and see if things work now. I'll give you feedback once it is done.
>
> Thanks again,
>
> Samuel


Ok, so I've tested with the corrected indxing for the output (sortie) and it is now working. As for the input problem I had, it now seems to be gone...

Thanks again for your time, I'm gonna be able to continue my work now

Samuel