将mxArray传递给mexCallMatlab失败

时间:2014-11-22 03:09:28

标签: matlab mex

我正在编写一个调用conv2函数的mex文件。此mex文件将获得大小为(M, N)的图片,并使用conv2多次应用卷积。

#include "mex.h"

void myconv( mxArray *Ain, mxArray *Kernel, mxArray *&Aout )
{

    mxArray *rhs[3];

    rhs[0] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
    rhs[1] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
    rhs[2] = mxCreateString       ( "same" );

    double *ainPtr = mxGetPr( Ain   );
    mxSetPr( rhs[0], ainPtr         );
    mxSetM ( rhs[0], mxGetM(Ain)    );
    mxSetN ( rhs[0], mxGetM(Ain)    );

    double *kernelPtr = mxGetPr( Kernel );
    mxSetPr( rhs[1], kernelPtr          );
    mxSetM ( rhs[1], mxGetM(Kernel)     );
    mxSetN ( rhs[1], mxGetN(Kernel)     );

    mexCallMATLAB(1, &Aout, 3, rhs, "conv2");

    mxSetPr( rhs[0], NULL ); 
    mxSetPr( rhs[1], NULL );

}

void myconv_combine( mxArray *Ain, mxArray *&Aout )
{

    mxArray *mask = mxCreateDoubleMatrix( 1, 5, mxREAL );

    double *maskPtr = mxGetPr( mask );
    maskPtr[0] = 0.05; 
    maskPtr[1] = 0.25; 
    maskPtr[2] = 0.4; 
    maskPtr[3] = 0.25; 
    maskPtr[4] = 0.05;

    mxArray *maskTranspose = mxCreateDoubleMatrix( 0, 0, mxREAL );
    mxSetPr( maskTranspose, maskPtr      );
    mxSetM ( maskTranspose, mxGetN(mask) );
    mxSetN ( maskTranspose, mxGetM(mask) );

    mxArray *AinConvolved = mxCreateDoubleMatrix( (mwSize)mxGetM(Ain), (mwSize)mxGetN(Ain), mxREAL );
    double *AinConvolvedPtr = mxGetPr( AinConvolved );
    myconv( Ain, mask, AinConvolved );

    // Some modifications.
    mxArray *Temp = mxCreateDoubleMatrix( (mwSize)mxGetM(Ain), (mwSize)mxGetN(Ain), mxREAL );
    double *TempPtr = mxGetPr( Temp );
    for( int i = 0; i < (mwSize)mxGetM(Ain)*(mwSize)mxGetN(Ain); i++ )
            TempPtr[ i ] = 2.0*AinConvolvedPtr[ i ];

    // Some other convolution.
    mxArray *TempConvolved = mxCreateDoubleMatrix( (mwSize)mxGetM(Ain), (mwSize)mxGetN(Ain), mxREAL );
    double *TempConvolvedPtr = mxGetPr( TempConvolved );
    myconv( Temp, maskTranspose, TempConvolved );

    // Some other modifications.
    double *AoutPtr = mxGetPr( Aout );
    for( int i = 0; i < (mwSize)mxGetM(Ain)*(mwSize)mxGetN(Ain); i++ )
            AoutPtr[ i ] = 2.0*TempConvolvedPtr[ i ];


}


void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

   mxArray *Ain  = mxCreateDoubleMatrix( 100, 100, mxREAL );
   mxArray *Aout = mxCreateDoubleMatrix( 100, 100, mxREAL );

   myconv_combine( Ain, Aout );


}

在我的实际代码中,当它到达行时:

myconv( Temp, maskTranspose, TempConvolved );

MATLAB崩溃,我不知道为什么会发生这种情况,不幸的是我无法在上面提供的示例代码中复制相同的错误。在我的实际代码中,图像按行成功卷积:

myconv( Ain, mask, AinConvolved );

但是,只要它想要应用第二个卷积:

myconv( Temp, maskTranspose, TempConvolved );

崩溃,当我调试它时,会在mexCallMATLAB函数上调用myconv时发生。 Temp / TempConvolvedAin / AinConvolved之间的区别是什么导致前者在mexCallMATLAB时崩溃?

有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

重用数据缓冲区

重用mxArray *mask mxArray *maskTransposed的数据指针是一个麻烦,因为MATLAB具有严格的引用计数机制,因为共享数据数组是MATLAB内存优化的重要组成部分。相反,使用mxDuplicateArray复制整个内容:

mxArray *maskTranspose = mxDuplicateArray(mask);

有一个未记录的mxCreateSharedDataCopy模仿MATLAB的懒惰复制机制,但对于5个元素的数组来说真的有点过分。

mxArray

之前进行多余的问题mexCallMATLAB初始化

另外,在致电mxArray *AinConvolved之前,请不要忘记初始化mexCallMATLAB。只需传递一个NULL指针,它就会为你创建它。如果你不是,它只会擦除旧的(将其发送到垃圾收集)并为conv2的输出创建一个新的。这让我想起这表明你的代码中存在这个问题:

mxArray *AinConvolved = mxCreateDoubleMatrix(mxGetM(Ain), mxGetN(Ain), mxREAL);
double *AinConvolvedPtr0 = mxGetPr(AinConvolved);
myconv(Ain, mask, AinConvolved);
double *AinConvolvedPtr = mxGetPr(AinConvolved);
mexPrintf("%p\n%p\n", AinConvolvedPtr0, AinConvolvedPtr);

MATLAB输出:

00000000B852FA20
0000000026B8EB00

正如您所看到的,如果您在使用mxGetPr之前尝试使用mexCallMATLAB附带的指针,则可能使用了错误的数据,可能已经释放了内存..

使用imfilter

自动分离过滤

另请注意,如果您有imfilter,则不需要实现可分离卷积,因为它内置了该功能。只需查看imfilter.m并注意{{ 1}}功能。请参阅here for more information

试试看,我会发布一个测试。