【问题标题】:MATLAB mexCallMatlab causes crashMATLAB mexCallMatlab 导致崩溃
【发布时间】:2015-12-05 17:48:03
【问题描述】:

我正在尝试在 mex 中开发一个功能。该功能的目的应该是将窗口滑动到 3D 图像上并在窗口内应用一些功能。目前我被卡住了,因为当算法到达padarray 函数的调用时,MATLAB 崩溃了。

到目前为止,我写了这几行代码

#include <iostream>
#include "mex.h"
#include "matrix.h"       

using namespace std;

void mexFunction(int nlhs,mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    #define O_IMAGE       plhs[0]
    #define I_IMAGE       prhs[0]
    #define I_PADSIZE     prhs[1]
    #define I_FUN         prhs[2]
    #define I_OPTION      prhs[3]

  // Argument Checking:
  if(nrhs < 1 || nrhs > 4) /* Check the number of arguments */
    mexErrMsgTxt("Wrong number of input arguments.");
  else if(nlhs > 1)
    mexErrMsgTxt("Too many output arguments.");

  // Variable declarations
  static const char padding[] = "symmetric";
  const char *windowShape;
  const mwSize *dim;
  mwSize *dimPad;
  mwSize ndim;
  double *pad, *windowSize, *thetaStep, *phiStep;
  mxArray *inputFun[4], *inputPadFun[3], *input_image, *imagePad, *output_image;

  /*Get dimensions of input image*/
  ndim = mxGetNumberOfDimensions(I_IMAGE);
  dim = mxGetDimensions(I_IMAGE);

  /* Create dimensions of padded image*/
  dimPad = (mwSize *) mxCalloc(ndim, sizeof(mwSize));
  dimPad = (mwSize *) memcpy((void *) dimPad,(void *) dim, ndim*sizeof(mwSize));
  pad = mxGetPr(I_PADSIZE);
  for (int i=0;i<ndim;++i)
  {
      dimPad[i] += 2*pad[i];
  }

  /*Get pointer to the input image*/
  input_image = (mxArray *) mxGetData(I_IMAGE);

  /* Create output image*/
  O_IMAGE = mxCreateNumericArray(ndim, dim, mxDOUBLE_CLASS, mxREAL);
  output_image = (mxArray *) mxGetData(O_IMAGE);

  /* Create padded image*/
  imagePad = mxCreateNumericArray(ndim, dimPad, mxDOUBLE_CLASS, mxREAL);

  // Padding input matrix
  inputPadFun[0] = input_image;
  inputPadFun[1] = (mxArray *)(pad);
  inputPadFun[2] = (mxArray *)(padding);
  mexCallMATLAB(1, &imagePad, 3, inputPadFun, "padarray");

  // Clean UP
  mxFree(dimPad);
  mxDestroyArray(imagePad);
}

我检查了mexCallMATLAB 的输入和输出图像的尺寸,它们似乎是正确的。我真的不明白我做错了什么。任何帮助是极大的赞赏!

【问题讨论】:

  • 当我做错记忆时,我通常会遇到带有 mex 文件的 Matlab chrash。检查您是否正确创建了imagePad
  • 感谢您的建议。如何检查内存是否分配正确?我检查了尺寸是否正确,dimdimPad 都具有预期值。我在调用函数之前不使用imagePad,因此我不明白我怎么能对内存做错事。
  • 如果imagePad 不够大,无法存储填充后的数组,则内存访问错误!
  • 我检查了 ndim = 3 并且没问题 dimPad = [42 42 42] 这也没关系,因为原始图像是 32x32x32 而填充数组是 5x5x5
  • 我认为您的 padding 字符串有些问题。对于inputPadFun 的第三个参数,尝试使用mxCreateString 而不是将padding 转换为指向mxArray 的指针。您也不需要投射pad。这已经是一个mxArray 指针,所以只需执行prhs[1]I_PADSIZE

标签: c matlab mex sliding-window


【解决方案1】:

有几个有问题的演员表。

由于paddouble*,所以您在这里进行了无意义的转换:

(mxArray *)(pad)

padding 同样是const char[],你不能这样做

(mxArray *)(padding)

在以下行中,mxGetDatavoid* 返回到带有 原始类型doublesingle 等)的基础数据的缓冲区,但您正在转换发给mxArray*:

(mxArray *) mxGetData(prhs[0]);

请记住,mxArray 是 MathWorks 定义的不透明对象类型,您必须使用它们的函数来创建这些对象。你也只能处理指向它们的指针。

还有其他问题……


代码

这是一个 C++ 示例,说明如何更改代码:

// padarray_BugsFree.cpp
#include <iostream>
#include "mex.h"
#include "matrix.h"       

void mexFunction(int nlhs,mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  if(nrhs != 2)
    mexErrMsgTxt("Wrong number of input arguments:\n\t"
            "Iout = padarray_BugsFree(I,pad)");
  if(nlhs > 1)
    mexErrMsgTxt("Too many output arguments:\n\t"
            "Iout = padarray_BugsFree(I,pad)");

  if(!(mxIsDouble(prhs[0]) && mxIsDouble(prhs[1])))
      mexErrMsgTxt("Inputs must be double");

  mwSize ndim = mxGetNumberOfDimensions(prhs[0]);
  const mwSize *dim = mxGetDimensions(prhs[0]);

  if (ndim != mxGetNumberOfElements(prhs[1]))
      mexErrMsgTxt("pad must be equal to ndims(I)");

  const double *pad = mxGetPr(prhs[1]);
  mwSize *dimPad = (mwSize *) mxCalloc(ndim, sizeof(mwSize));
  for (int i=0; i<ndim; ++i) {
      dimPad[i] = dim[i] + 2*pad[i];
  }

  mxArray *imagePad = mxCreateNumericArray(ndim, dimPad, mxDOUBLE_CLASS, mxREAL);
  mxFree(dimPad);

  // Padding input matrix
  mxArray *padding = mxCreateString("symmetric");
  mxArray *inputPadFun[3];
  inputPadFun[0] = const_cast<mxArray*>(prhs[0]);
  inputPadFun[1] = const_cast<mxArray*>(prhs[1]);
  inputPadFun[2] = padding;
  mexCallMATLAB(1, &imagePad, 3, inputPadFun, "padarray");
  mxDestroyArray(padding);

  // do something with the padded image and generate output
  plhs[0] = mxDuplicateArray(imagePad); // in place of useful operations
  mxDestroyArray(imagePad);
}

演示

>> I = magic(3)
I =
     8     1     6
     3     5     7
     4     9     2
>> pad = [2 2]
pad =
     2     2
>> padarray_BugsFree
Error using padarray_BugsFree
Wrong number of input arguments:
    Iout = padarray_BugsFree(I,pad) 
>> Iout = padarray_BugsFree(I,pad)
Iout =
     5     3     3     5     7     7     5
     1     8     8     1     6     6     1
     1     8     8     1     6     6     1
     5     3     3     5     7     7     5
     9     4     4     9     2     2     9
     9     4     4     9     2     2     9
     5     3     3     5     7     7     5

备注

使用以下帖子作为参考,了解如何使用mexCallMATLAB

您还可以按如下方式构建 RHS 输入数组:

mxArray *inputPadFun[] = {const_cast<mxArray*>(prhs[0]),
                          const_cast<mxArray*>(prhs[1]), padding};
mexCallMATLAB(1, &imagePad, 3, inputPadFun, "padarray");

【讨论】:

  • 美丽:D。所以我对选角的怀疑确实是正确的。
  • 非常感谢。明天我会尝试你的解决方案,但它肯定会奏效,我会接受它。让我检查一下我是否理解正确:如果我有原始类型,我不能将它们转换为mxArray * 来创建mxArray * 但我需要使用matlab的特定功能?
  • @BugsFree 对。除了void* 之外,您通常不能(以有意义的方式)在指针之间进行转换。例如,将double 转换为single 很好,但将double* 转换为single* 是没有意义的。
  • @rayryeng 确实如此。这里有很多时髦的选角。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2020-12-02
  • 2013-11-11
  • 2011-01-24
  • 2015-02-23
  • 2011-04-23
相关资源
最近更新 更多