Problem in using mxSetPr
3 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
AP
el 21 de Nov. de 2014
Comentada: James Tursa
el 18 de Abr. de 2017
I am writing a function within in a mex file which calls a MATLAB function. Unfortunately, when it comes to mxSetPr, MATLAB crashes and does not proceed further. Could someone kindly tell me how I can fix this?
void myfun( double *Ain , double *Aout,
int AnRows , int AnCols,
double *kernel, int kernelnRows, int kernelnCols )
{
mxArray *rhs[3], *lhs[1];
rhs[0] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
rhs[1] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
rhs[2] = mxCreateString ( "same" );
mxSetPr( rhs[0], Ain );
mxSetM ( rhs[0], AnRows );
mxSetN ( rhs[0], AnCols );
mxSetPr( rhs[1], kernel );
mxSetM ( rhs[1], kernelnRows );
mxSetN ( rhs[1], kernelnCols );
mexCallMATLAB(1, lhs, 3, rhs, "conv2");
Aout = mxGetPr( lhs[0] );
}
0 comentarios
Respuesta aceptada
Geoff Hayes
el 23 de Nov. de 2014
The array must be in dynamic memory; call mxCalloc to allocate this memory. Do not use the ANSI® C calloc function, which can cause memory alignment issues leading to program termination. If pr points to static memory, memory leaks and other memory errors can result.
Did you use mxCalloc to allocate memory to Ain and kernel? That being said, I did try the following test function
void test()
{
mxArray* myMxArray = 0;
double* myDblArray = 0;
myMxArray = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
myDblArray = mxCalloc(4,sizeof(double));
if (myMxArray!=NULL && myDblArray!=NULL)
{
mxSetPr(myMxArray,myDblArray);
mxSetM(myMxArray,2);
mxSetN(myMxArray,2);
mxFree(myDblArray);
mxDestroyArray(myMxArray);
}
}
and the above crashed at the mxSetPr line. So I am a little puzzled by the above. James Tursa would most likely know what is wrong with the above code.
-------
The only time I've seen mxSetPr being used in for output (the lhs) of the mexFunction, so if I had to do something similar to what you are doing, I would have tried the following
void myfun2(double *Ain , int AnRows , int AnCols,
double *kernel, int kernelnRows, int kernelnCols,
mxArray **lhs)
{
mxArray *rhs[3];
double *ptr;
// create the mxArrays
rhs[0] = mxCreateNumericMatrix( AnRows, AnCols, mxDOUBLE_CLASS, mxREAL );
rhs[1] = mxCreateNumericMatrix( kernelnRows, kernelnCols, mxDOUBLE_CLASS, mxREAL );
rhs[2] = mxCreateString ( "same" );
// copy the Ain and kernel data
ptr = mxGetPr(rhs[0]);
memcpy(ptr,Ain,sizeof(double)*AnRows*AnCols);
ptr = mxGetPr(rhs[1]);
memcpy(ptr,kernel,sizeof(double)*kernelnRows*kernelnCols);
mexCallMATLAB(1, lhs, 3, rhs, "conv2");
// destroy the mxArrays
mxDestroyArray(rhs[0]);
mxDestroyArray(rhs[1]);
mxDestroyArray(rhs[2]);
}
Note in the above how memcpy is used to copy the data from the Ain and Kernel arrays to the destination mxArrays. Note also that for every create of an mxArray, we must destroy or free memory allocated to that array.
For the case of the left-hand side result of the convolution, we pass an mxArray into this function as
mxArray **lhs
As (presumably) memory will be dynamically allocated to it within the conv2 function, the caller of myfun2 does not need to allocate memory to this parameter, but the caller will be responsible for freeing the memory. For example,
// do some work to create the Ain and Kernel matrices
// declare the output matrix from the 2D convolution
mxArray *convMtx = 0;
// call the function to do the 2D convolution
myfun2(Ain, AnRows, AnCols,kernel,kernelnRows,kernelnCols,&convMtx);
if (convMtx!=NULL)
{
// do some stuff with convMtx
// destroy mxArray
mxDestroyArray(convMtx);
}
See how we pass the convMtx into the function as &convMtx.
3 comentarios
Geoff Hayes
el 24 de Nov. de 2014
Without knowing the sizes of your matrices or how often you expect to call this function, I can't comment on your assertion that copying will significantly reduce the efficiency and speed of your code.
James Tursa
el 18 de Abr. de 2017
Commenting on an old post ...
In the first code section above:
void test()
{
mxArray* myMxArray = 0;
double* myDblArray = 0;
myMxArray = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
myDblArray = mxCalloc(4,sizeof(double));
if (myMxArray!=NULL && myDblArray!=NULL)
{
mxSetPr(myMxArray,myDblArray); <-- (1)
mxSetM(myMxArray,2);
mxSetN(myMxArray,2);
mxFree(myDblArray); <-- (2)
mxDestroyArray(myMxArray); <-- (3)
}
}
"... and the above crashed at the mxSetPr line. So I am a little puzzled by the above. James Tursa would most likely know what is wrong with the above code."
Line (1) attaches the pointer myDblArray to the mxArray myMxArray (and at the same time removes myDblArray from the garbage collection list). Note that this attaches the actual pointer value, not some type of copy.
Line (2) frees the memory behind myDblArray, which now means that myMxArray has an invalid pointer as its real data pointer.
Line (3) attempts to free the memory behind myDblArray again. But this pointer is invalid because of (2), hence the crash.
The fix is to remove line (2).
Más respuestas (0)
Ver también
Categorías
Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!