Search code examples
c++matlabmex

Issue about logical output from MEX function in MATLAB


Why is the output always 1 from my MEX function although it was expected to be 0?

I wrote the following MEX source code shown below

#include "mex.h"

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

  /* Create matrix for the return argument. */
  plhs[0] = mxCreateLogicalMatrix(1,1);

  /* Assign pointers to each input and output. */
  x = mxGetLogicals(prhs[0]); //input
  y = mxGetLogicals(plhs[0]); //output

  /* Calculations. */
  if (*x == 0) *y = 1;
  else *y = 0;
}

and the following appears:

y = test(5)

y =

     1

Solution

  • I'd like to point you to the documentation of mxGetLogicals. Part of the documentation says:

    Returns

    Pointer to the first logical element in the mxArray. The result is unspecified if the mxArray is not a logical array.

    What you are passing is a double precision number, not a logical. By doing this, you will get undefined behaviour. As such, there are three ways you can resolve this error:

    1. Pass an actual logical value to the function.
    2. Leave everything as is, but change what you are returning. Instead of *y = 1 and *y = 0, change this to true and false respectively, but the input has to be double.
    3. You basically must change any reference to logical / bool to double. Specifically, change mxGetLogicals to mxGetPr so you can get a pointer to a double precision real array. You'll also need to change mxCreateLogicalMatrix to mxCreateDoubleMatrix and you'll have to change your pointers from bool to double.

    Option #1 - Passing a logical value to the function:

    You simply need to do:

    y = test(false);
    

    or:

    y = test(true);
    

    Running this with these changes gives me the following:

    >> y = test(false)
    
    y =
    
         1
    
    >> y = test(true)
    
    y =
    
         0
    

    Option #2 - Input type is double, output type is bool:

    These changes are what you need to make:

    #include "mex.h"
    
    void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
    {
      double *x;
      bool *y; // Change
    
      /* Create matrix for the return argument. */
      plhs[0] = mxCreateLogicalMatrix(1,1);
    
      /* Assign pointers to each input and output. */
      x = mxGetPr(prhs[0]); //input - Change
      y = mxGetLogicals(plhs[0]); //output
    
      /* Calculations. */
      if (*x == 0) *y = true; // Change
      else *y = false;
    }
    


    Running this code with the above changes gives me:

    >> y = test(0)
    
    y =
    
         1
    
    >> y = test(5)
    
    y =
    
         0
    

    Option #3 - Change bool behaviour to double:

    #include "mex.h"
    
    void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
    {
      double *x,*y; // Change
    
      /* Create matrix for the return argument. */
      plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); // Change
    
      /* Assign pointers to each input and output. */
      x = mxGetPr(prhs[0]); //input - Change
      y = mxGetPr(plhs[0]); //output - Change
    
      /* Calculations. */
      if (*x == 0) *y = 1;
      else *y = 0;
    }
    

    Running this code with the above changes gives me:

    >> y = test(0)
    
    y =
    
         1
    
    >> y = test(5)
    
    y =
    
         0