2016-04-14 4 views
0

ich mit 2D-Arrays arbeite mit Doppelzeiger definiert, e.g,Rückdoppelzeiger 2D-Matrix in mex Funktion

double** array; 
array = (double**) calloc(numRows, sizeof(double*)); 
for (int i = 0; i < numRows; i++) 
{ 
    array[i] = (double*) calloc(numCols, sizeof(double)); 
    /* then array[i][j] = values */ 
} 

// code to return matlab array 
plhs[0] = mxCreateDoubleMatrix(numRows, numCols, mxREAL); 

// memory copy 
// ????????? 

for (i = 0; i < numRows; i++){ 
     free(array[i]); 
    }  
free(array); 

I array in Matlab zurückkehren möchten. Eine Ausführungs ich für den // memory copy Teil bis jetzt habe, und ich denke, dass es in Ordnung ist, korrigieren bitte ich bin:

stacked1D = mxGetPr(plhs[0]); 
int n = 0; 
for (int r = 0; r < max_degree; r++) 
    for (int c = 0; c < n_vars; c++) 
     stacked1D[n++] = stacked2D[r][c]; 

Ich frage mich, mich, ob wir es mit einer mem-copy Funktion wie diese mxSetPr(OUT, *stacked2D); tun können, was nicht funktioniert in dieser Syntax.

Könnten Sie bitte einen Tipp-Erklärung oder mögliche Antwort geben?

+2

Erstens gibt es keine Notwendigkeit zu verwenden 'calloc' in ein C++ Programm. Wenn Sie Speicher dynamisch zuweisen möchten, verwenden Sie 'new []'. Zweitens, [siehe diese Antwort] (http://stackoverflow.com/questions/23458486/delete-2d-array-c/23458646#23458646), wie Sie ein 2D-Array effizienter zuweisen, wo Sie den gesamten Speicherpool zuweisen statt in Blöcken, wie es dein Code jetzt macht. – PaulMcKenzie

+0

@PaulMcKenzie Ehrfürchtige Verbindung. Es kam mir nie in den Sinn, dass du es so machen könntest. – NathanOliver

+0

Was den memcpy-Teil betrifft, müssen Sie immer noch das Array zuweisen (mit der Methode, bei der Sie nur zwei Aufrufe von 'new []' brauchen), aber um die Daten zu kopieren, benötigen Sie einen einzelnen 'memcpy' von der Quelle zu Zielpool. Wenn Sie bei Ihrer Methode bleiben, brauchen Sie eine Schleife, die 'memcpy'' n' für eine 'n x n'-Matrix aufruft. – PaulMcKenzie

Antwort

0

Zeilen- und Spalteniterationen sollten in Ihrem Code umgekehrt sein, und was PaulMcKenzie vorgeschlagen hat, obwohl es im Prinzip eine gute Idee ist, wird nicht mit Mex-Matrizen funktionieren (sie sind Spalte für Spalte ausgelegt, also mit dieser Methode Sie müsste mit M[column][row] auf Ihre Matrix zugreifen, die un-natürlich und verwirrend ist).

Alternativ können Sie einen einfachen Wrapper wie die folgenden verwenden:

template <class T, class I = unsigned> 
struct MatrixWrapper 
{ 
    T *data; 
    I nrows, ncols; 

    MatrixWrapper() 
     { clear(); } 
    MatrixWrapper(T *data_, I nrows_, I ncols_) 
     { set(data_,nrows_,ncols_); } 

    inline void clear() 
     { data = NULL; nrows = ncols = 0; } 

    inline void set(T *data_, I nrows_, I ncols_) 
     { data = data_; nrows = nrows_; ncols = ncols_; } 

    inline T& operator() (I r, I c) const 
     { return data[ r + nrows*c ]; } 
}; 

und Ihre Mex Funktion würde wie folgt aussehen:

// allocate a temporary matrix 
double *M_data = new double[ nrows*ncols ]; 
MatrixWrapper<double> M(M_data, nrows, ncols); 

// access values with M(i,j) as a "normal" matrix 

// allocate a Mex output 
plhs[0] = mxCreateDoubleMatrix(nrows, ncols, mxREAL); 
MatrixWrapper<double> out0(mxGetPr(plhs[0]), nrows, ncols); 

// copy to the Mex output 
for (unsigned c = 0; c < ncols; c++) 
for (unsigned r = 0; r < nrows; r++) 
    out0(r,c) = M(r,c); 

// free temporary allocation 
M.clear(); 
delete[] M_data; 
Verwandte Themen