I have to use a MEX function which is supposed to allocate a matrix and fill it (for example, make an identity matrix). Here is a code sample:
#include <stdlib.h>
#include "mex.h"
void sample(int n, double** T)
{
(*T) = (double*)malloc(n*n*sizeof(double));
int i, j;
if ((*T) == NULL)
{
return;
}
else
{
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (i != j)
(*T)[i*n + j] = 0;
else
(*T)[i*n + j] = 1;
}
}
}
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
mwSize n = *(mwSize*)mxGetData(prhs[0]);
double *T;
plhs[0] = mxCreateDoubleMatrix(1, (size_t)n*(size_t)n, mxREAL);
T = mxGetPr(plhs[0]);
sample(n, &T);
}
I use it like this:
n = 5;
T = [];
T = sample(5, T);
This call returns a 1-by-0 empty matrix. So, it doesn't allocate a n-by-n matrix and doesn't fill it.
You have three very crucial errors and a few minor hiccups:
This line:
mwSize n = *(mwSize*)mxGetData(prhs[0]);at the beginning of your MEX function.This makes absolutely no sense. We can clearly see that the input is a single integer.
mxGetDataactually gets a pointer to the actual data that is coming in as inputs into the MEX function, yet you are casting the pointer tomwSizethen dereferencing it. I have absolutely no idea what this would give you, but it's definitely not right. What you can do instead is get the actual pointer to the data usingmxGetPrwhere the pointer would provide you with data that conforms to adoubleprecision real type. Because this would be an integer, you can cast this toint:Because of the correction with (1), you can now allocate your matrix without explicitly casting with
size_t. This I wouldn't call an error, but it's more of a style correction:The most important error of all.
Take note that your
samplefunction inside your MEX code accepts a pointer to adoublepointer in memory for the purposes of modifying the matrix that you created in your main MEX gateway (i.e.mexFunction). However, you first allocate the memory for the matrix to be written to the output, but are allocating the memory again inside yoursamplefunction. Because of this, you are actually creating another pointer to memory and writing the data to this pointer and not with the original pointer that you had passed to the function. Specifically, insidesampleyou have this code:Therefore, upon exit of this function the memory that you intended to modify has not been modified. The point is that allocation inside the function is not required as you have already allocated the memory of the matrix outside of the function. This can be removed from your code.
This is very important in terms of memory access. Remember that MATLAB is a column-major based language, which means that the columns of a matrix are laid out in a contiguous fashion instead of the rows like in languages such as C. Therefore, your method of accessing the matrix given that your matrix is of size
m x nwithmrows andncolumns should be(*T)[j*m + i]where the indexiaccesses the rows andjaccesses the columns. Right now you have it set to(*T)[i*n + j]. For now as your matrix shares the same rows and columns and that you are creating an identity matrix, either way of accessing is the same but be weary of rectangular sized matrices.Therefore, the corrected code for your
samplefunction is thus:Once you run this code, it now produces the desired results. However, you have created a
n*nrow vector and not an x nmatrix, but I'm assuming you did that on purpose. To get this to run, I placed your source in a file calledsample.c, compiled it then ran it:If you wish to create a
n x nmatrix instead, change the call tomxCreateDoubleMatrixso that both the first and second arguments are set ton:This isn't an error but worth nitpicking about. Your function only expects 1 input so there's no need to submit
Tas the second parameter. Your code does not check for a second parameter anyway. In addition, you need to include the proper headers for your code to compile:The final code that is corrected is thus:
Just for the sake of argument, this is what happens if change
mxCreateDoubleMatrixso that it outputs an x nmatrix: