How to get a pointer to 2D array when writing a C source Mex file?
10 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Mustafa Aydin
am 19 Jul. 2018
Bearbeitet: James Tursa
am 10 Feb. 2019
Hi, I'm trying to write a highly simple C source .mex file (function) that takes a 1 x n vector and n x n matrix, and yields their matrix product, again a 1 x n vector (all the arrays are of binary and I'm doing computations for binary case). My concern is how to get a pointer to 2D array,(e.g the line arr = mxGetDoubles(prhs[1]);) I tried mxGetDoubles as it works for 1xn arrays, but I came across with the warning ": assignment from incompatible pointer type [-Wincompatible-pointer-types]". I then tried mxGetData; it did not give any warnings yet when I called the function from the command window, MATLAB crashed and was forced to close.
I would be highly appreciated if anyone can help me out. Thanks and here is the whole .c code:
/*==========================================================
* arrayMultiplier.c
*
* Multiplies a 1xN matrix with a N X N matrix
* and outputs a 1xN matrix
*
* The calling syntax is:
* outMatrix = arrayProduct(vector, array)
*========================================================*/
#include "mex.h"
/* The computational routine */
void arrayMultiplier( double *vec, double **arr, mwSize n ,double *z){
for (mwSize i=0; i<n; i++) {
for(mwSize j=0; j<n; j++) {
z[i] += vec[j]*arr[j][i];
}
z[i] = (double)((int)z[i] % 2);
}
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
double *vec;
double **arr;
mwSize nr;
double *outMatrix;
nr = mxGetN(prhs[0]); /*The "n" parameter of the 1 x n output matrix*/
vec = mxGetDoubles(prhs[0]);
arr = mxGetData(prhs[1]); /* This is where the warning appears */
/* creating the output matrix */
plhs[0] = mxCreateDoubleMatrix(1,nr,mxREAL);
/* get a pointer to the real data in the output matrix */
outMatrix = mxGetDoubles(plhs[0]);
/* call the computational routine */
arrayMultiplier(vec,arr,nr,outMatrix);
}
0 Kommentare
Akzeptierte Antwort
James Tursa
am 19 Jul. 2018
Bearbeitet: James Tursa
am 19 Jul. 2018
You can't use the [j][i] indexing syntax with the pointer returned by mxGetDoubles. You would need to set up a separate pointer array in order to use this syntax (never worth it IMO), or just do the indexing calculations manually (my preference).
E.g., make these changes in mexFunction:
double *arr; // **arr changed to *arr
:
arr = mxGetDoubles(prhs[1]);
And make these changes in arrayMultiplier:
void arrayMultiplier( double *vec, double *arr, mwSize n ,double *z){ // **arr changed to *arr
:
z[i] += vec[j] * (*arr++);
Since the 2D matrix is stored column-wise and the vector is on the left of the multiply, you can access the 2D matrix in a simple linear fashion with the *arr++ syntax. A functionally equivalent version using explicit indexing would have been this (but with extra unneeded indexing calculations for this particular case):
z[i] += vec[j] * arr[j+i*n]; // Manually calculate the equivalent linear index
3 Kommentare
KayLee Trickey
am 9 Feb. 2019
I know you say this isn't worth it, but how would you set up a separate pointer array to use the [i][j] syntax? My code uses that syntax way more then the original poster, and I'm trying to figure out how to get it to work correctly. I'm getting the same incompatible error.
James Tursa
am 10 Feb. 2019
Bearbeitet: James Tursa
am 10 Feb. 2019
I don't have MATLAB or C handy at the moment, but an outline for a 2d matrix is something like this:
#define ARR(i,j) arr[j][i]
double **arr;
mwSize i, j, m, n;
:
m = mxGetM(prhs[1]);
n = mxGetN(prhs[1]);
arr = (double **) mxMalloc( n * sizeof(*arr) );
arr[0] = mxGetDoubles(prhs[1]);
for( j=1; j<n; j++ ) {
arr[j] = arr[j-1] + m; // The column pointers
}
:
// Then use arr[j][i] in your code, i is row and j is column, 0-based
// Or use ARR(i,j) in your code, i is row and j is column, 0-based
:
mxFree(arr);
Note that when using arr[j][i] syntax the j comes first, since MATLAB array memory is column ordered. But when using the macro ARR(i,j) the i comes first since that is how I have defined the macro to work.
If you really want to use the syntax arr[i][j] with i (row) first and j (column) second, you would have to copy all of the 2D matrix values to new memory (essentially transposing it). This, IMO, is too high a price to pay and I don't include that code here.
Weitere Antworten (1)
Walter Roberson
am 19 Jul. 2018
mxGetDoubles will always be pointer to double, with the pointer being to the column-major linear storage of the data. To use this as a 2D array at the C level, you need to cast it to the appropriate double vec[m,n] declaration.
2 Kommentare
KayLee Trickey
am 9 Feb. 2019
I am trying to do something similar to original poster, how do you cast it as the appropriate double declaration? I am knew to C and 2D arrays and pointers all all new to me.
In my c code, I use a lot of arr[i][j] indexing syntax.
Siehe auch
Kategorien
Mehr zu Resizing and Reshaping Matrices finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!