2015-04-09 2 views
1

Матрица, которую я мог бы вернуть, имеет только первый элемент правильно, а все остальные - нули. Я попытался следовать, как предлагалось в этом link; но для меня это не тренировалось. Некоторая помощь будет оценена по достоинству.MEX: Как вернуть матрицу из C++/C в MATLAB

Выход:

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

ответ

2

Виновником прямо здесь:

*p2 = B[0]; 

Это эквивалентно только копированию первого значения B и помещению его в первый слот p2, который является первой строкой первого столбца вывода. Вам необходимо скопировать всю матрицу .

помнить также, что матрицы в MATLAB являются колонка основным, так что вы должны быть осведомлены о том, как вы индекса в p2. Однако Armadillo states that you access elements in column-major format if you just access the matrices using single linear indices. Поэтому вместо того, чтобы делать *p2 = B[0];, сделайте это:

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

спасибо, это сработало. Поскольку я плохо разбираюсь в C++, и указатель всегда меня смущает, не могли бы вы ответить на еще один вопрос? In, p2 [i] = B [i]; 'LHS - ** указатель + i приращений **; а RHS - это ** массив **. Почему компилятор не жалуется на несоответствие типов? –

+1

@ DushyantKumar 'p2 [i]' является синтаксическим сахаром для '* (p2 + i)'. Не существует рассогласования типа, поскольку выполнение 'p2 [i]' выполняет операцию разыменования. Помните, что массивы являются непрерывными фрагментами памяти, поэтому то, что вы на самом деле делаете, когда вы выполняете 'p2 [i]', - это то, что вы получаете доступ к элементу, начинающемуся с позиции, где начинается 'p2', и вы перемещаете байты с плавающей запятой i над. Доступ к массиву и арифметика указателя на самом деле одно и то же, но '* (p2 + i)' на самом деле известно немного быстрее. Тем не менее, всегда пишите для удобочитаемости перед исполнением. Напишите так, как вам удобно. – rayryeng

Смежные вопросы