简体   繁体   中英

MEX: How to return a matrix from C++/ C to MATLAB

The matrix, that I could return, has only first element correct and all others are zeros. I tried to follow as suggested in this link ; but, it did not workout for me. Some help would be appreciated.

Output:

>> Matlab_mex_Testing
B1 =
1.0000        0        0
     0   1.0000        0
     0        0   1.0000
     0        0        0


B =
    1    0    0
    0    0    0
    0    0    0
    0    0    0

Matlab code:

Dir2  = '/home/dkumar/Mex_Codes_DKU/MexCode_Working/Mex_CPP_N_ARMADILLO_Codes_DKU_makefile_Working';

% MEX
cd(Dir2);
[y, B] = normpdfDKU(1/2,0,1);

%Matlab declared
B1 = eye(4,3)

% Identical matrix returned from MEX
B

CPP:

#include "mex.h"
#include <math.h>

#include "/home/dkumar/armadillo-4.600.3/include/armadillo"
using namespace arma;

using namespace std;

#define pi (3.141592653589793)

extern void _main();

const int numInputArgs  = 3;
const int numOutputArgs = 2;

// Function declarations.
// -----------------------------------------------------------------
double  getMatlabScalar    (const mxArray* ptr);
double& createMatlabScalar (mxArray*& ptr);


int TestingLibraries() ;   // declared and defined in In Include_4_TSNNLS.c and Include_4_TSNNLS.h

// Function definitions.
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[],
          int nrhs, const mxArray *prhs[]) {

  // Check to see if we have the correct number of input and output
  // arguments.
  if (nrhs != numInputArgs)
    mexErrMsgTxt(" DKU-1: Incorrect number of input arguments");
  if (nlhs != numOutputArgs)
    mexErrMsgTxt("DKU-2: Incorrect number of output arguments");

  // Get the inputs.
  double x  = getMatlabScalar(prhs[0]);
  double mu = getMatlabScalar(prhs[1]);
  double v  = getMatlabScalar(prhs[2]);

  // Create the output. It is also a double-precision scalar.
  double& p = createMatlabScalar(plhs[0]);

  // Compute the value of the univariate Normal at x.
  p = exp(-(x-mu)*(x-mu)/(2*v)) / sqrt(2*pi*v);

  // CREATE ARMA::mat and print 
  mat B = eye<mat>(4,3);

  //Print B
  B.print();

  // Trying to return B as second output
   mwSize sz[2];
   sz[0] = B.n_rows  ; // Matlab is row first
   sz[1] = B.n_cols  ;
   //mxArray* pOUT = mxCreateNumericArray(2, sz, mxDOUBLE_CLASS, mxREAL);
   plhs[1] = mxCreateNumericArray(2, sz, mxDOUBLE_CLASS, mxREAL);
   //Get a pointer to pOUT
   double* p2 = (double*)mxGetData(plhs[1]);
   *p2 = B[0];

}

double getMatlabScalar (const mxArray* ptr) {

  // Make sure the input argument is a scalar in double-precision.
  if (!mxIsDouble(ptr) || mxGetNumberOfElements(ptr) != 1)
    mexErrMsgTxt("The input argument must be a double-precision scalar");

  return *mxGetPr(ptr);
}

double& createMatlabScalar (mxArray*& ptr) { 
  ptr = mxCreateDoubleMatrix(1,1,mxREAL);
  return *mxGetPr(ptr);
}

The culprit is right here:

*p2 = B[0];

This is equivalent to only copying the first value of B and putting it into the first slot of p2 , which is the first row, first column of the output. You need to copy the entire matrix over.

Also remember that matrices in MATLAB are column major so you need to be cognizant of the way you index into p2 . However, Armadillo states that you access elements in column-major format if you just access the matrices using single linear indices . Therefore, instead of doing *p2 = B[0]; , do this:

for (int i = 0; i < B.n_elem; i++)
    p2[i] = B[i];

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