MEX:如何从C++/C向MATLAB返回矩阵

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

本文关键字:MATLAB 返回 C++ MEX      更新时间:2023-10-16

我可以返回的矩阵只有第一个元素是正确的,其他元素都是零。我试着按照这个链接中的建议去做;但是,这对我来说并没有什么好处。如果能给我一些帮助,我将不胜感激。

输出:

>> 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代码:

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);
}

罪魁祸首就在这里:

*p2 = B[0];

这相当于只复制B的第一个值,并将其放入p2的第一个槽,即输出的第一行、第一列。您需要复制整个矩阵。

还要记住,MATLAB中的矩阵是主矩阵,因此您需要了解对p2进行索引的方式。然而,Armadillo指出,如果您只使用单个线性索引访问矩阵,则可以访问列主格式的元素。因此,与其执行*p2 = B[0];,不如执行以下操作:

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