For Programmers: Free Programming Magazines  


Home > Archive > Matlab > August 2007 > Variable-size arrays in MEX-files









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Variable-size arrays in MEX-files
Anders Korsbäck

2007-08-30, 8:15 am

Hello,

I'm trying to speed up one of my m-files by turning some
repetitive for-loops into C-code. However, I have run into a
problem: I can't seem to find any way to make variable-size
arrays work in the computational routine I'm building, while
they work perfectly well in stand-alone (non-mex) C-codes
compiled on UNIX. Anyways, here is the code so far:

#include "mex.h"
#include "matrix.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void pull(double zL[], double pullforce[], double dt[],
double simtime[],
int N[], double T[], double P[], double d[])
{

const int nroftimesteps=*simtime/(*dt);

const double kb=1.3806504e-23;
const double eta=2.414e-5*pow(10,(247.8/(T[0]-140.0)));
const double h=100*kb*T[0]/(d[0]*d[0]);

const double g = (P[0]*kb*T[0])/d[0];
const double gamma = 3.0*M_PI*eta*d[0];

double x_end[3][nroftimesteps]; /* <--- this is line 26
which refuses to compile */

zL[0]=nroftimesteps;

}

void mexFunction( int nlhs , mxArray *plhs[] , int nrhs ,
const mxArray *prhs[] )
{
double *pullforce, *dt, *simtime, *T, *P, *d, *zL;
int *N;
pullforce = mxGetPr(prhs[0]);
dt = mxGetPr(prhs[1]);
simtime = mxGetPr(prhs[2]);
N = mxGetPr(prhs[3]);
T = mxGetPr(prhs[4]);
P = mxGetPr(prhs[5]);
d = mxGetPr(prhs[6]);

plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);

zL = mxGetPr(plhs[0]);

pull(zL,pullforce,dt,simtime,N,T,P,d);

}

When I compile it on MATLAB 7.0.4, I get the following:

mex pulltest_hydro4.c
Error pulltest_hydro4.c: 26 integer expression must be
constant
Warning pulltest_hydro4.c: 26 local `array 3,1 of double
x_end' is not referenced
Warning pulltest_hydro4.c: 39 assignment of pointer to int
to pointer to double
1 errors, 2 warnings


Am I just doing something wrong, or don't variable-size
arrays in C work in mex-files? Do mex-files have some way of
their own to handle arrays?

My best regards,
Anders Korsbäck
Michael Wild

2007-08-30, 8:15 am

Anders Korsbäck wrote:
> Hello,
>
> I'm trying to speed up one of my m-files by turning some
> repetitive for-loops into C-code. However, I have run into a
> problem: I can't seem to find any way to make variable-size
> arrays work in the computational routine I'm building, while
> they work perfectly well in stand-alone (non-mex) C-codes
> compiled on UNIX. Anyways, here is the code so far:
>
> #include "mex.h"
> #include "matrix.h"
> #include <stdio.h>
> #include <stdlib.h>
> #include <math.h>
>
> void pull(double zL[], double pullforce[], double dt[],
> double simtime[],
> int N[], double T[], double P[], double d[])
> {
>
> const int nroftimesteps=*simtime/(*dt);
>
> const double kb=1.3806504e-23;
> const double eta=2.414e-5*pow(10,(247.8/(T[0]-140.0)));
> const double h=100*kb*T[0]/(d[0]*d[0]);
>
> const double g = (P[0]*kb*T[0])/d[0];
> const double gamma = 3.0*M_PI*eta*d[0];
>
> double x_end[3][nroftimesteps]; /* <--- this is line 26
> which refuses to compile */
>
> zL[0]=nroftimesteps;
>
> }
>
> void mexFunction( int nlhs , mxArray *plhs[] , int nrhs ,
> const mxArray *prhs[] )
> {
> double *pullforce, *dt, *simtime, *T, *P, *d, *zL;
> int *N;
> pullforce = mxGetPr(prhs[0]);
> dt = mxGetPr(prhs[1]);
> simtime = mxGetPr(prhs[2]);
> N = mxGetPr(prhs[3]);
> T = mxGetPr(prhs[4]);
> P = mxGetPr(prhs[5]);
> d = mxGetPr(prhs[6]);
>
> plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
>
> zL = mxGetPr(plhs[0]);
>
> pull(zL,pullforce,dt,simtime,N,T,P,d);
>
> }
>
> When I compile it on MATLAB 7.0.4, I get the following:
>
> mex pulltest_hydro4.c
> Error pulltest_hydro4.c: 26 integer expression must be
> constant
> Warning pulltest_hydro4.c: 26 local `array 3,1 of double
> x_end' is not referenced
> Warning pulltest_hydro4.c: 39 assignment of pointer to int
> to pointer to double
> 1 errors, 2 warnings
>
>
> Am I just doing something wrong, or don't variable-size
> arrays in C work in mex-files? Do mex-files have some way of
> their own to handle arrays?
>
> My best regards,
> Anders Korsbäck



actually, the code you show shouldn't compile at all! arrays on the
stack must have dimensions known at compile time which is definitely not
the case in your code.

for such a thing you either need malloc/calloc and free in C or new[]
and delete[] in C++. However, in C++ std::vector often is the better
choice...


hth

michael
Titus

2007-08-30, 8:15 am


"Anders Korsbäck" <anders.korsback@helsinki.fi> schrieb im Newsbeitrag
news:fb6ab4$det$1@ginger.mathworks.com...
> Hello,
>
> I'm trying to speed up one of my m-files by turning some
> repetitive for-loops into C-code. However, I have run into a
> problem: I can't seem to find any way to make variable-size
> arrays work in the computational routine I'm building, while
> they work perfectly well in stand-alone (non-mex) C-codes
> compiled on UNIX. Anyways, here is the code so far:
>
> #include "mex.h"
> #include "matrix.h"
> #include <stdio.h>
> #include <stdlib.h>
> #include <math.h>
>
> void pull(double zL[], double pullforce[], double dt[],
> double simtime[],
> int N[], double T[], double P[], double d[])
> {
>
> const int nroftimesteps=*simtime/(*dt);
>
> const double kb=1.3806504e-23;
> const double eta=2.414e-5*pow(10,(247.8/(T[0]-140.0)));
> const double h=100*kb*T[0]/(d[0]*d[0]);
>
> const double g = (P[0]*kb*T[0])/d[0];
> const double gamma = 3.0*M_PI*eta*d[0];
>
> double x_end[3][nroftimesteps]; /* <--- this is line 26
> which refuses to compile */
>
> zL[0]=nroftimesteps;
>
> }
>
> void mexFunction( int nlhs , mxArray *plhs[] , int nrhs ,
> const mxArray *prhs[] )
> {
> double *pullforce, *dt, *simtime, *T, *P, *d, *zL;
> int *N;
> pullforce = mxGetPr(prhs[0]);
> dt = mxGetPr(prhs[1]);
> simtime = mxGetPr(prhs[2]);
> N = mxGetPr(prhs[3]);
> T = mxGetPr(prhs[4]);
> P = mxGetPr(prhs[5]);
> d = mxGetPr(prhs[6]);
>
> plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
>
> zL = mxGetPr(plhs[0]);
>
> pull(zL,pullforce,dt,simtime,N,T,P,d);
>
> }
>
> When I compile it on MATLAB 7.0.4, I get the following:
>
> mex pulltest_hydro4.c
> Error pulltest_hydro4.c: 26 integer expression must be
> constant
> Warning pulltest_hydro4.c: 26 local `array 3,1 of double
> x_end' is not referenced
> Warning pulltest_hydro4.c: 39 assignment of pointer to int
> to pointer to double
> 1 errors, 2 warnings
>
>
> Am I just doing something wrong, or don't variable-size
> arrays in C work in mex-files? Do mex-files have some way of
> their own to handle arrays?
>
> My best regards,
> Anders Korsbäck


Hi Anders,

the reason may be the following: it depends on the C-compiler
you are using. Do you compile your MEX file on a windows
machine? Which compiler do you use, LCC?

double x_end[3][nroftimesteps];

is a non-standard extension the gcc compiler allows, but it's
not handled by many other compilers (as you see it complaining).

Now: is x_end something you want to pass back to MATLAB?
In this case, just do something like:
plhs[1] = mxCreateDoubleMatrix(nroftimesteps, 1, mxREAL);
x_end = mxGetPr(plhs[1]);
and pass this to your pull function.

Otherwise: use mxMalloc to reserve memory:
double *x_end[3];
x_end[0] = mxMalloc(3*nroftimesteps*sizeof(double))
;
x_end[1] = x_end[0]+nroftimesteps;
x_end[2] = x_end[1]+nroftimesteps;

and mxFree(x_end[0]);
at the end of your mex-file.

Titus


Peter Boettcher

2007-08-30, 8:58 pm

"Anders Korsbäck" <anders.korsback@helsinki.fi> writes:

> void mexFunction( int nlhs , mxArray *plhs[] , int nrhs ,
> const mxArray *prhs[] )
> {
> double *pullforce, *dt, *simtime, *T, *P, *d, *zL;
> int *N;
> pullforce = mxGetPr(prhs[0]);
> dt = mxGetPr(prhs[1]);
> simtime = mxGetPr(prhs[2]);
> N = mxGetPr(prhs[3]);
> T = mxGetPr(prhs[4]);
> P = mxGetPr(prhs[5]);
> d = mxGetPr(prhs[6]);
>
> plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
>
> zL = mxGetPr(plhs[0]);
>
> pull(zL,pullforce,dt,simtime,N,T,P,d);
>
> }
>
> When I compile it on MATLAB 7.0.4, I get the following:
>
> mex pulltest_hydro4.c
> Error pulltest_hydro4.c: 26 integer expression must be
> constant
> Warning pulltest_hydro4.c: 26 local `array 3,1 of double
> x_end' is not referenced
> Warning pulltest_hydro4.c: 39 assignment of pointer to int
> to pointer to double
> 1 errors, 2 warnings


Others have addressed your question, but I will point out another
potential problem. The warning for line 39 says that mexGetPr returns
a double pointer, but N is an int pointer. There are two
possibilities:

1- You really are passing an integer array, which you set up in MATLAB
using int32() or something. If that's the case, use mxGetData instead
of mxGetPr, and double-check the data type before doing it.

2- You are passing a standard double-precision MATLAB array, which you
happen to know contains integer values. In that case, you MUST use a
double pointer to access the values in MATLAB. You can cast them to
ints one at a time as you use them.

-Peter
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com