简体   繁体   中英

memcpy function calling inside mex

I have an interesting problem. Namely like that; I am trying to use std::memcpy function inside by mex function and calling that mex function inside MATLAB like that;

I2 = b_filter(I);

When I copy the whole image, it works well;

plhs[0] =  mxCreateDoubleMatrix(mxGetM(plhs[0]), mxGetN(plhs[0]), mxREAL);          
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) *mxGetM(plhs[0]) * mxGetN(plhs[0]));

But when I try to copy some part of image

plhs[0] =  mxCreateDoubleMatrix(100, 100, mxREAL);              
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) * 100 * 100);

it doesn't give right image part but gives unmeaningful pixel values.

So what is going on here?

Ha Ha! You've been caught by one of the nastiest of mex file nuances! It's got me before too. Arrays in mex functions are stored in column order not row order, so you:

You still use column-first indexing like in Matlab, though

Blog URL

Try this page too for a nice picture of the ordering.

图来自Mathworks

Finally I would recommend reading this thread to get a better idea behind the difference of C and MATLAB matrix memory being column-ordered.

As explained by @macduff, MATLAB uses a column-major order to store arrays, while C arrays are row-major.

Here is a sample implementation showing how to copy part of a matrix.

matrix_slice_mex.c

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *in, *out;
    mwIndex i,j;
    mwSize numRows;

    /* input checks */
    if (nrhs != 1 || nlhs > 1) {
        mexErrMsgIdAndTxt("MATLAB:nargchk", "Wrong number of arguments.");
    }
    if (mxGetNumberOfDimensions(prhs[0])>2 || !mxIsDouble(prhs[0])) {
        mexErrMsgIdAndTxt("MATLAB:wrongDims", "Expecting 2D double matrix.");
    }
    if (mxGetM(prhs[0])<100 || mxGetN(prhs[0])<100) {
        mexErrMsgIdAndTxt("MATLAB:wrongDims", "Matrix size must be >= 100x100.");
    }

    /* extract sub-matrix */
    plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
    out = mxGetPr(plhs[0]);
    in = mxGetPr(prhs[0]);
    numRows = mxGetM(prhs[0]);
    for(j=0; j<100; j++) {
        for(i=0; i<100; i++) {
            *out++ = in[i + numRows*j];
        }
    }
}

And to test this:

x = rand(1000);
y = x(1:100,1:100);
yy = matrix_slice_mex(x);
isequal(y,yy)

You could have also used memcpy to copy each of the columns (one for-loop instead)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM