mxGetPr crashing for no reason

조회 수: 6 (최근 30일)
James
James 2014년 1월 13일
댓글: James Tursa 2014년 1월 14일
Hello,
I am trying to create a mex file which will modify the contents of the array in plhs, but whenever I run the code it crashes when I try to assign the adress of a double* to plhs[0]. Below is my code...
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int l = (int)mxGetScalar(prhs[0]);
int nslc = (int)mxGetScalar(prhs[1]);
double *spc = (double*)mxGetData(prhs[2]);
int Tnpx_w = (int)mxGetScalar(prhs[3]);
int Tnpx_h = (int)mxGetScalar(prhs[4]);
double *Tpx_w0 = (double*)mxGetData(prhs[5]);
double *Tpx_h0 = (double*)mxGetData(prhs[6]);
int Inpx_w = (int)mxGetScalar(prhs[7]);
int Inpx_h = (int)mxGetScalar(prhs[8]);
double *Ipx_w = (double*)mxGetData(prhs[9]);
double *Ipx_h = (double*)mxGetData(prhs[10]);
double *a = (double*)mxGetData(prhs[11]);
double *D = (double*)mxGetData(prhs[12]);
double alpha = (double)mxGetScalar(prhs[13]);
double OMEGA = (double)mxGetScalar(prhs[14]);
double *W = (double*)mxGetData(prhs[15]);
double *img = (double*)mxGetData(prhs[16]);
int dims[3] = {Tnpx_h,Tnpx_w,nslc};
int s,m,n;
double L, Tpx_w, Tpx_h;
double TposX, TposY, TposZ;
double SposX, SposY, SposZ;
double IX, IY;
int IXi, IYi;
double VX, VY, VZ;
double *ts_posX = (double*)mxMalloc(Tnpx_w*sizeof(double));
double *ts_posY = (double*)mxMalloc(Tnpx_h*sizeof(double));
double *img0;
// plhs[0] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
printf("test0");
img0 = mxGetPr(plhs[0]);
printf("test1");
//begin code ...
}
An example of how I call this in matlab is...
img0=Pdts(l,nslices,spacing,Tnpx_w,Tnpx_h,Tpx_w0,Tpx_h0,Inpx_w,Inpx_h,Ipx_w,Ipx_h,a,D,alpha,OMEGA,W(count),img);
this is in a large loop where img0 is a 3d array initially set to all zeros. Each call should update the array img0 to add in new values to what is in img0 when Pdts is called. The c code compiles fine, but it is crashing on the line
img0 = mxGetPr(plhs[0]);
I know this because the first printf statement will execute, but the second will not. If I add in the commented out line
plhs[0] = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
it will not crash and run. However, each time I run it I reallocate a new space within the memory and so img0 does not retain the values from previous calls to Pdts. Could anyone give me some help with getting this working? Thanks

채택된 답변

James Tursa
James Tursa 2014년 1월 13일
편집: James Tursa 2014년 1월 13일
If you want to operate on a calling workspace variable in-place iteratively, you will have to pass that variable into the mex routine each iteration. In other words, you need to create this variable at your m-file level and pass it into your mex routine, NOT create this variable as a plhs[0]. E.g., if you pass it in as the first argument, then you will be using img0 = mxGetPr(prhs[0]) each time inside the mex routine. There will be no explicit output at the m-file level, nor should you create any plhs[0] inside the mex routine. E.g., the m-file calling syntax would be:
Allocate img0 once, then inside your loop do this:
Pdts(img0,l,nslices,spacing,Tnpx_w,Tnpx_h,Tpx_w0,Tpx_h0,Inpx_w,Inpx_h,Ipx_w,Ipx_h,a,D,alpha,OMEGA,W(count),img);
and inside the mex routine Pdts you would be modifying prhs[0] in-place each time.
CAUTION: This in-place modification violates the strict const assumption of the prhs inputs. If img0 is shared with any other variable at the m-file level you will inadvertantly modify that other variable as well and possibly get incorrect results from your code.
Alternatively to operating on the variable in-place, you can duplicate it each time if you are willing to accept the extra data copying involved. E.g.,
Allocate img0 once, then inside your loop do this:
img0 = Pdts(img0,l,nslices,spacing,Tnpx_w,Tnpx_h,Tpx_w0,Tpx_h0,Inpx_w,Inpx_h,Ipx_w,Ipx_h,a,D,alpha,OMEGA,W(count),img);
And then inside the mex routine have this statement to create the plhs[0]:
plhs[0] = mxDuplicateArray(prhs[0]);
img0 = mxGetPr(plhs[0]);
As a side note, you should be using mwSize for dims, not int. E.g.,
mwSize dims[3] = {Tnpx_h,Tnpx_w,nslc};

추가 답변 (1개)

James
James 2014년 1월 13일
Awesome, thanks for the answer, that makes more sense. I did a work around by saving the output into a temp array imgT and then adding that to img0.
imgT = Pdts(...);
img0 = img0 + imgT;
not how I wanted to do it but I guess it works. I did not know that you could pass a non-const variable to the mex function and modify it, I figured that would be caught during compilation and it would not work. Anyways, thanks for the answer, I may try to modify my function to get it to work that way. In terms of using mwSize, I am not very familiar with MATLAB so whenever possible I would like to use native c data types and functions when possible (eg. I use printf rather than mexPrintf). I feel this would be general as the code wont be full of mex specifica calls and can be transfered into pure C code more easily. Is there a practical reason why I should use mwSize over int?
  댓글 수: 1
James Tursa
James Tursa 2014년 1월 14일
The practical reason for using mwSize over int is because that is what the official function signature uses in the doc ... and that using int will likely crash MATLAB on a 64-bit system (if it even compiles) since the mxCreateNumericArray call would be accessing invalid memory (accessing dims as an array of 64-bit integers while you only gave it an array of 32-bit integers).

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Write C Functions Callable from MATLAB (MEX Files)에 대해 자세히 알아보기

태그

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by