Problem in using mxSetPr
    7 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 C Matrix API 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!


