# How to use mxCreateNumericArray

30 ビュー (過去 30 日間)
Christopher Grose 2019 年 5 月 13 日
Edited: James Tursa 2019 年 5 月 14 日
I am building a mex function, but am having difficulty creating a vector of integers. My code throws about 10 errors, all of which around the declaration of 'gn' and plhs[0]. I'm just trying to make a xynum long vector of class int16. Why is it so difficult?
void findnegs(double *phi, int gnum, int xynum, int *gn, double *adj, double *newphi, double *dphidtSum)
{
long i,g;
double u,s;
for (i = 0; i<xynum; i++)
{
s = 0;
for (g = 0; g<gnum; g++)
{
u = dphidtSum[g+i*gnum]/phi[g+i*gnum];
if (newphi[g+i*gnum]<0 & u<s)
{
s = u;
gn[i] = g;
}
}
}
}
/* The gateway function that replaces the "main".
*plhs[] - the array of output values
*prhs[] - the array of input values
*/
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/* DECLARATIONS*/
int gnum, xynum, *gn;
/* INPUTS */
gnum = mxGetScalar(prhs[0]);
xynum = mxGetScalar(prhs[1]);
phi = mxGetPr(prhs[2]);
newphi = mxGetPr(prhs[3]);
dphidtSum = mxGetPr(prhs[4]);
/* OUTPUTS */
plhs[0] = mxCreateNumericArray(xynum,1,mxINT16_CLASS); /*Creates a matrix*/
plhs[1] = mxCreateDoubleMatrix(xynum,1,mxREAL); /*Creates a matrix*/
gn = mxGetInt16s(plhs[0]); /*Set to be the first of the output values*/
adj = mxGetPr(plhs[1]); /*Set to be the first of the output values*/
/* CALL ROUTINE */
}

#### 1 件のコメント

Jan 2019 年 5 月 13 日
How do you compile the code? Which API version are you using? mxGetInt16s belongs to the R2018a API, but and mxGetPr to R12017b. Decide for one of them.
Which error message do you get? Please share them with the readers. This is more efficient thabn letting us guess, what you see.

サインイン to comment.

### 採用された回答

James Tursa 2019 年 5 月 13 日

This line is incorrect (wrong function and signature):
plhs[0] = mxCreateNumericArray(xynum,1,mxINT16_CLASS); /*Creates a matrix*/
plhs[0] = mxCreateNumericMatrix(xynum,1,mxINT16_CLASS,mxREAL); /*Creates a matrix*/
Also, these lines will not work:
int gnum, xynum, *gn;
:
gn = mxGetInt16s(plhs[0]); /*Set to be the first of the output values*/
An int on your system is almost surely a 32-bit integer, not a 16-bit integer. You need to make sure your pointer definition matches exactly what is in memory. E.g., you can probably use a short int for this:
int gnum, xynum;
short *gn;
:
gn = mxGetInt16s(plhs[0]); /*Set to be the first of the output values*/
That will mean you need to change this signature:
void findnegs(double *phi, int gnum, int xynum, int *gn, double *adj, double *newphi, double *dphidtSum)
void findnegs(double *phi, int gnum, int xynum, short *gn, double *adj, double *newphi, double *dphidtSum)
But this begs the question, are integer calculations in the findnegs function now going to overflow your 16-bit integers in gn? You may need to adjust your code to make sure this isn't a problem.

#### 6 件のコメント

Christopher Grose 2019 年 5 月 13 日
Thanks for that explanation. 16 bit integers are still useful in this case but that will change some other plans.
Perhaps a final question. The mex function is crashing when called in matlab. I've actually commented out everything in the findnegs function so that nothing is executed but it still fails. It looks to fail around the line
plhs[0] = mxCreateNumericArray(xynum,1,mxINT16_CLASS,mxREAL); /*Creates a matrix*/
since report shows
Stack Trace (from fault):
and perhaps it is associated with these warnings during compiling:
Building with 'MinGW64 Compiler (C)'.
C:\Users\Chris\Desktop\New Phase Field\findnegsC.c: In function 'mexFunction':
C:\Users\Chris\Desktop\New Phase Field\findnegsC.c:55:45: warning: passing argument 2 of 'mxCreateNumericArray_730' makes pointer from integer without a cast [-Wint-conversion]
plhs[0] = mxCreateNumericArray(xynum,1,mxINT16_CLASS,mxREAL); /*Creates a matrix*/
^
In file included from C:\Program Files\MATLAB\R2018b/extern/include/mex.h:43:0,
from C:\Users\Chris\Desktop\New Phase Field\findnegsC.c:7:
C:\Program Files\MATLAB\R2018b/extern/include/matrix.h:275:30: note: expected 'const mwSize * {aka const long long unsigned int *}' but argument is of type 'int'
#define mxCreateNumericArray mxCreateNumericArray_730
^
C:\Program Files\MATLAB\R2018b/extern/include/matrix.h:1247:1: note: in expansion of macro 'mxCreateNumericArray'
mxCreateNumericArray(mwSize ndim, const mwSize *dims, mxClassID classid, mxComplexity flag);
^~~~~~~~~~~~~~~~~~~~
MEX completed successfully.
how can this be corrected?
Christopher Grose 2019 年 5 月 14 日
I was looking at
edit([matlabroot '/extern/examples/refbook/matrixDivide.c']);
and noticed that the syntax for mxCreateNumericArray is not the same as mxCreateDoubleMatrix. I changed the code to:
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/* DECLARATIONS*/
int xynum;
short gnum, *gn;
mwSignedIndex dims[2];
/* INPUTS */
gnum = mxGetScalar(prhs[0]);
xynum = mxGetScalar(prhs[1]);
phi = mxGetPr(prhs[2]);
newphi = mxGetPr(prhs[3]);
dphidtSum = mxGetPr(prhs[4]);
/* OUTPUTS */
dims[0] = xynum;
dims[1] = 1;
plhs[0] = mxCreateNumericArray(2,dims,mxINT16_CLASS,mxREAL); /*Creates a matrix*/
plhs[1] = mxCreateDoubleMatrix(xynum,1,mxREAL); /*Creates a matrix*/
// gn = mxGetInt16s(plhs[0]); /*Set to be the first of the output values*/
gn = (short *) mxGetData(plhs[0]); /*Set to be the first of the output values*/
adj = mxGetPr(plhs[1]); /*Set to be the first of the output values*/
/* CALL ROUTINE */
}
which works.
But is there a way to do this without declaring and assigning each level of dims? Can I just put the values in the mxCreateNumericArray line to simplify/save some overhead?
James Tursa 2019 年 5 月 14 日
You didn't read my initial Answer closely enough. I told you to replace your mxCreateNumericArray call with a mxCreateNumericMatrix call for exactly the reason you specify ... it avoids the dims stuff if you only want a 2D result.
The reason you were still crashing is because you had the wrong arguments for mxCreateNumericArray.

サインイン to comment.