How to get a pointer to 2D array when writing a C source Mex file?

9 views (last 30 days)
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);
}

Accepted Answer

James Tursa
James Tursa on 19 Jul 2018
Edited: James Tursa on 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 Comments
KayLee Trickey
KayLee Trickey on 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
James Tursa on 10 Feb 2019
Edited: James Tursa on 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.

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 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 Comments
KayLee Trickey
KayLee Trickey on 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.

Sign in to comment.

Categories

Find more on Resizing and Reshaping Matrices in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!