Asked by Carine
on 22 Mar 2012

Hi,

I am trying to make a mex file from a C one. I have a few questions. The main one is the first lines of my program are

#include "fftw3.h"

#include <fftw3.h>

however and although the fftw3 library is installed on my computer, it seems that Matlab is unable to find it as when I compile my program it says

undefined reference to `fftw_plan_many_dft'

etc. It is not the only library that include, I also have the standard stdlib.h, string.h, math.h but they don't seem to be a problem. How could I do for Matlab to understand where to find the library? The fftw3.h is in /usr/include.

Another question is: is it possible to mex non void functions, for example int or double or should I modify them? Finally a very basic question: can I put my C functions in another file and include them to the main mex (the one with mxFunction) with an #include myfunction.h? Cheers.

Answer by Ken Atwell
on 23 Mar 2012

As Friedrich states, you will need to add a few switches to you call to MEX:

- -I to indicated the directory where your headers (.h) files are (/usr/include in your case)
- -L to indicated the directory where you library (.so) files are
- -l to indicate the name of the library file to linkage against

stdlib.h, string.h are not a problem because they are part of your compiler's distribution, and FFTW is not.

As to the return types of your function, the MEX API entry point must be void:

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

Use nlhs and plhs to return values.

You can put other functions in their own files, or within the C file containing mexFunction -- it is really a matter of style. If you do use separate files, you will need to add them to your MEX command line.

Sign in to comment.

Answer by James Tursa
on 26 Mar 2012

What happens when you try this:

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

#include <time.h>

#ifdef _WIN32

#include <windows.h>

#else

#include <sys/utsname.h>

#endif

#include "mex.h"

void gft_1dPartitions(unsigned int N, int *partitions) {

[...]

partitions[pcount] = ep;

partitions[pOff-pcount] = en;

[...]

return;

}

void mexFunction( int nlhs, mxArray *plhs[],

int nrhs, const mxArray *prhs[] )

{

int N, *partitions;

int taille,k;

/* get the scalar value of the input x */

/* note: mxGetScalar returns a value, not a pointer */

N = mxGetScalar(prhs[0]);

/* assign a pointer to the output */

taille = 2*round(log2(N))+1;

plhs[0] = mxCreateNumericMatrix(1, taille, mxINT32_CLASS, mxREAL);

partitions = (int*) mxGetData(plhs[0]);

/* Call the subroutine. */

gft_1dPartitions(N, partitions);

return;

}

Sign in to comment.

Answer by Carine
on 26 Mar 2012

Hi,

Thanks for your answers Friedrich and Ken, little by little, I am starting to understand how mex works. For the second part of my question, I know the mxFunction should be void. What I meant is to include a C function which returns an integer or a double as

int *ThisFunction(int N){

...

return var}

For one function it is easy to change but as I have many depending on each other, that would be much more convenient for me if possible. Sorry for being so confusing and I hope I have been more clear this time ;-)

James Tursa
on 26 Mar 2012

Sign in to comment.

Answer by Titus Edelhofer
on 26 Mar 2012

Hi,

you don't need to change your code. Yes, the mex interface is with void, but there is nothing wrong doing something like the following

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])

{

// N is the first input argument

int N = (int) mxGetPr(prhs[0])[0];

int result = ThisFunction(int N);

plhs[0] = mxCreateDoubleScalar(result);

}

Or did I miss something?

Titus

Sign in to comment.

Answer by Carine
on 26 Mar 2012

Well, Titus, I am sure I am missing something as I had tried something similar but it doesn't work:

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

#include <time.h>

#ifdef _WIN32

#include <windows.h>

#else

#include <sys/utsname.h>

#endif

#include "mex.h"

int *gft_1dPartitions(unsigned int N) {

/*void gft_1dPartitions(unsigned int N, int *partitions) {*/

int *partitions;

[...]

partitions[pcount] = ep;

partitions[pOff-pcount] = en;

[...]

return partitions;

}

void mexFunction( int nlhs, mxArray *plhs[],

int nrhs, const mxArray *prhs[] )

{

int N, *partitions;

int taille,k;

/* get the scalar value of the input x */

/* note: mxGetScalar returns a value, not a pointer */

N = mxGetScalar(prhs[0]);

partitions = gft_1dPartitions(N);

/* assign a pointer to the output */

taille = 2*round(log2(N))+1;

plhs[0] = mxCreateNumericMatrix(1, taille, mxINT32_CLASS, mxREAL);

/*partitions = (int*) mxGetData(plhs[0]);*/

/* Call the subroutine. */

/*gft_1dPartitions(N, partitions);*/

return;

}

And if I try to run it: mxPartitionGFT(16), it only gives me 0's.

Sign in to comment.

Answer by Titus Edelhofer
on 26 Mar 2012

Hi,

I see. I would suggest the following:

int *pr;

[...]

// this is the result from the function:

partitions = gft_1dPartitions(N);

// this is the pointer to the result data in plhs:

pr = (int*) mxGetData(plhs[0]);

// copy partitions to pr

memcpy(pr, partions, taille*sizeof(int));

[...]

// probably you need to free the memory?

free(partitions);

Titus

Sign in to comment.

Answer by Carine
on 28 Mar 2012

Thanks for your answers. James, this does work but for other applications, I would like to make it work with the C function being of type (int *) instead of void. Titus, I have tried to follow your advice but still can't make it. When I compile it, I've got a message "assignation from a pointer type incompatible" for memcpy. And I don't know if a mxMalloc is useful in the C-function but it doesn't seem to help or work so I comment it. Here is the entire code:

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

#include <time.h>

#ifdef _WIN32

#include <windows.h>

#else

#include <sys/utsname.h>

#endif

#include "mex.h"

int *gft_1dPartitions(unsigned int N) {

/*void gft_1dPartitions(unsigned int N, int *partitions) {*/

int sf = 1;

int cf = 1;

int width = 1;

int pcount = 0;

int pOff;

int *partitions;

int ep,en;

/*partitions = (int *)mxMalloc((round(log2(N))*2+1)*sizeof(int));*/

pOff = round(log2(N))*2-1;

while (sf < N/2) {

ep = cf+width/2-1;

en = N-cf+width/2+1;

if (ep > N) ep = N;

if (width/2 == 0)

ep+=1;

partitions[pcount] = ep;

partitions[pOff-pcount] = en;

pcount++;

sf = sf+width;

if (sf > 2) width *= 2;

cf = sf+width/2;

}

partitions[pOff+1] = -1;

return partitions;

}

void mexFunction( int nlhs, mxArray *plhs[],

int nrhs, const mxArray *prhs[] )

{

int N, *partitions, *pr;

int taille,k, sizpart;

/* get the scalar value of the input x */

/* note: mxGetScalar returns a value, not a pointer */

N = mxGetScalar(prhs[0]);

/* assign a pointer to the output */

taille = 2*round(log2(N))+1;

partitions = gft_1dPartitions(N);

plhs[0] = mxCreateNumericMatrix(1, taille, mxINT32_CLASS, mxREAL);

pr = (int*) mxGetData(plhs[0]);

/* sizpart = mxGetElementSize(partitions);*/

memcpy(pr, partitions, taille*sizeof(int)); /*sizpart);*/

/* Call the subroutine. */

/*gft_1dPartitions(N, partitions);*/

free(partitions);

return;

}

Any other idea? Cheers.

Jan
on 28 Mar 2012

If you create an mxArray of type UINT32, be sure *not* to create an (int *) pointer to its data. This will crash on 64 bit machines. Better use a (uint32_T *) pointer.

Currently the function is writing to an un-allocated partitions* array. This cannot work.

Jan
on 28 Mar 2012

Sign in to comment.

Answer by Carine
on 25 Apr 2012

Thanks for all your support and sorry for not answering before but I was busy with other things. For the moment, I've transformed my C functions to be void and then avoid this problems but I am sure there is something obvious I don't understand (a newbie...). So, here is a part of the piece of code I run:

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

{

/* mwSize N; */

int N, *partitions;

int taille, i;

double *partdouble;

double *sig, *gft, *win, *tmp;

char *windowtype;

void *window;

mxArray *plhs1[1], *prhs1[1];

/* create a pointer to the real data in the input matrix */

sig = mxGetPr(prhs[0]);

/* get dimensions of the input matrix */

N = mxGetM(prhs[0]);

if (N == 1)

N = mxGetN(prhs[0]);

/* Compute partition sizes */

taille = 2*round(log2(N))+1;

partitions = mxMalloc(taille);

/* partitions = (int*) mxGetData(plhs[0]);*/

/* Call the subroutine. */

gft_1dPartitions(N, partitions);

mexPrintf("partitions = %d\n",partitions[1]);

/* create the output matrix */

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

/* plhs[0] = mxCreateNumericMatrix(1, taille, mxINT32_CLASS, mxREAL);*/

/* get a pointer to the real data in the output matrix */

gft = mxGetPr(plhs[0]);

gft[0] = (double)partitions[0];

if (nrhs == 1)

windowtype = "gaussian";

else

windowtype = mxArrayToString(prhs[1]); /*mexGetString*/

if (windowtype != "gaussian" && windowtype != "box")

mexErrMsgTxt("Window type must be gaussian or box");

if (windowtype == "gaussian")

window = &gaussian;

else

window = &box;

mexPrintf("window2 = %s\n", windowtype);

return;

}

So I have nearly emptied the function of its content. Then to run it, I do the following:

mex -I/usr/include -L/usr/lib64/ -lfftw3 gft1d.c

a = randn(1,16); gft1d(a)

It does print out what I have asked:

partitions = 2

window2 = gaussian

but then Matlab crashes. When I try to use the debugger using gdb, http://www.mathworks.es/help/techdoc/matlab_external/f32489.html#bq3wlv9-1, it just tells me

Program received signal SIGUSR1, User defined signal 1.

pthread_cond_wait@@GLIBC_2.3.2 ()

at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:165

165 62: movl (%rsp), %edi

and I have no clue what it means :-( Any help? Cheers

James Tursa
on 25 Apr 2012

At first glance, it looks like you are not calling mxMalloc correctly in this line:

partitions = mxMalloc(taille);

mxMalloc (like its C counterpart malloc) allocate the number of bytes requested, and I am guessing that taille is the number of *elements* you want for partitions, not the number of *bytes*. So do this instead:

partitions = mxMalloc(taille * sizeof(*partitions));

You should get in the habit of always using the form above for calling mxMalloc (or malloc) in your code. I.e., always have your coded line look like this pattern:

mypointer = malloc( (number_of_elements) * sizeof(*mypointer) );

You can get arguments both ways as to whether or not you should explicitly cast the result of malloc in the above line. In C++ you have to. In C it is optional. Leaving it out in C gives the compiler a chance to generate an error in the above line if the prototype for malloc is missing.

Sign in to comment.

Answer by Carine
on 26 Apr 2012

Thanks James! It does work. But now, if I include some more lines in the code, making use of the following function

void fft(int N, double *in, int stride) {

fftw_plan p;

p = fftw_plan_many_dft(1,&N, 1, (fftw_complex *)in, NULL, stride, 0, (fftw_complex *)in, NULL, stride, 0, FFTW_FORWARD, FFTW_ESTIMATE);

printf("fft\n");

fftw_execute(p);

fftw_destroy_plan(p);

}

and using the fftw3 library, Matlab crashes again at the moment of the call of fftw_plan_many_dft. As this code doesn't come from what I have written, I am even more lost :-(

The fft function is called in the following one:

void gaussian(double *win, int N, int freq) {

int i;

double x;

double sum;

for (i = 0; i<N*2; i+=2) {

x = i / (N*2+0.0);

win[i] = abs(freq)/sqrt(2*PI)*exp(-pow((x-0.5),2)*pow(freq,2)/2.0);

win[i+1] = 0.0;

sum += win[i];

}

/* Make sure the window area is 1.0*/

for (i = 0; i<N*2; i+=2) {

win[i] /= sum;

}

shift(win,N,-N/2);

printf("Gaussian shift\n");

fft(N,win,1);

printf("Gaussian fft\n");

}

Sign in to comment.

Answer by Carine
on 2 May 2012

As I cannot sort it out, I am now trying the suboptimal possibility of using the matlab fft by

void gaussian(double *win, int N, int freq) {

int i;

double x;

double sum;

for (i = 0; i<N*2; i+=2) {

x = i / (N*2+0.0);

win[i] = abs(freq)/sqrt(2*PI)*exp(-pow((x-0.5),2)*pow(freq,2)/2.0);

win[i+1] = 0.0;

sum += win[i];

}

/* Make sure the window area is 1.0*/

for (i = 0; i<N*2; i+=2) {

win[i] /= sum;

}

shift(win,N,-N/2);

/* fft(N,win,1); It doesn't work so use the Matlab fft*/

mexCallMATLAB(1,win,1,&win,"fft");

printf("Gaussian fft\n");

}

But mxCallMATLAB expects a mxArray type and I don't know how to transform my double *win input/output parameter to a mxArray. Could I ask your help again?

Cheers.

James Tursa
on 3 May 2012

The best way to turn win into an mxArray is to do it *before* you call gaussian. E.g.,

mxArray *mx;

double *win;

mx = mxCreateDoubleMatrix(1, N*2, mxREAL);

win = mxGetPr(mx);

gaussian( win, N, freq );

But if you can't do it that way for some reason, then you can copy the data inside gaussian(). E.g.,

void gaussian( etc ) {

:

mxArray *mx;

double *pr;

mx = mxCreateDoubleMatrix( 1, N*2, mxREAL );

pr = mxGetPr(mx);

for( i=0; i<N*2; i++ ) {

pr[i] = win[i];

}

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Friedrich (view profile)

## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/33117-how-to-include-libraries-in-a-mex-file#comment_69624

Sign in to comment.