8

I'm trying to learn how to use the C API to reading Matlab .mat files, but it's not working as I expected:

I'd like to just open a very simple .mat file called test.mat, read a value from the file and store it in a C variable. I've created test.mat in Matlab using the following commands:

> value = 3;
> save ("test.mat", "value")

Below is my C code, which doesn't even compile - the compiler doesn't seem to find the header files. See below the code for compiler output. What am I doing wrong here?

Code:

#include <stdlib.h>
#include <stdio.h>
#include <mat.h>
#include <matrix.h>

int main(int argc, char *argv[]) {
    double value;
    MATFile *datafile;
    datafile = matOpen("test.mat", "r");

    mxArray *mxValue;
    mxValue = matGetVariable(datafile, "value");

    matClose(datafile);
    value = *mxGetPr(mxArray);

    mxFree(mxArray);

    printf("The value fetched from the .mat file was: %f", value);

    return 0;
}

Compiler output:

$ make animate_shot
cc  -I/usr/local/MATLAB/R2011a/extern/include/   animate_shot.c   -o animate_shot
/tmp/cczrh1vT.o: In function `main':
animate_shot.c:(.text+0x1a): undefined reference to `matOpen'
animate_shot.c:(.text+0x2f): undefined reference to `matGetVariable'
animate_shot.c:(.text+0x3f): undefined reference to `matClose'
animate_shot.c:(.text+0x4b): undefined reference to `mxGetPr'
animate_shot.c:(.text+0x5e): undefined reference to `mxFree'
collect2: ld returned 1 exit status
make: *** [animate_shot] Error 1

(the -I flag is specified with the line CPPFLAGS=-I/usr/local/MATLAB/R2011a/extern/include/ in my makefile, and I've verified that the directory exists and contains the header files mat.h and matrix.h).

UPDATE:
I've found that the libraries I need to link in are libmat.so and libmx.so (according to this MathWorks help article), residing in /usr/local/MATLAB/R2011a/bin/glnxa64/ on my system. I've therefore updated my makefile to this:

CPPFLAGS =-I/usr/local/MATLAB/R2011a/extern/include/
LDFLAGS = -L/usr/local/MATLAB/R2011a/bin/glnxa64 -l mat -l mx

Now, running make gives the following command:

cc  -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/bin/glnxa64 -l mat -l mx  animate_shot.c   -o animate_shot

However, I still get the same errors. Any ideas?

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402

1 Answers1

7

This is a linker failure, not a compiler failure (and is unrelated to -I compiler option). You need to specify the directory in which the matlab .so files are located using -L flag and add a -l<matlab-lib-name> option to end of the compiler command that specifies the name of the matlab library.

For example:

cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/lib animate_shot.c -o animate_shot -lmatlab

(I don't know the exact directory into the which .so are located or the name of the matlab library)


Based on the comment providing further information:

cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/bin/glnxa64 animate_shot.c -o animate_shot -lmat -lmx

hmjd
  • 120,187
  • 20
  • 207
  • 252
  • OK. I've found where the *.so reside (`/usr/local/MATLAB/R2011a/bin/glnxa64/`) and I think I [figured out what the libraries are called](http://www.mathworks.se/help/techdoc/matlab_external/f19027.html) (`libmat.so` and `libmx.so`). However, I still cannot compile (getting the same errors as before). I've updated my answer with some details on the changes I've made. – Tomas Aschan Aug 31 '12 at 08:37
  • @TomasLycken, there is no update to your question. Based on what you have said I have updated my answer. – hmjd Aug 31 '12 at 08:43
  • Sorry - I wrote the comment, started writing the update and forgot to click "save" :P Now it's there. It seems it's doing what you're suggesting, but it's still not working... – Tomas Aschan Aug 31 '12 at 08:52
  • @TomasLycken, do you have a space character between the `-l` and the `mat`? If so remove it: `-lmat -lmx`. Not certain if this matters but the help for the Sun Forte compiler (which I _think_ you are using) does not show a space. – hmjd Aug 31 '12 at 08:56
  • Removed the space with no difference in errors. I'm running Ubuntu 12.04, so I assume I'm using the GCC compiler. `cc --version` gives me `cc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3` and a copyright notice. – Tomas Aschan Aug 31 '12 at 09:00
  • 1
    @TomasLycken, the `-l` options need to be at the _end_ of the compiler command (see this answer for why: http://stackoverflow.com/questions/9966959/noobish-linker-errors-when-compiling-against-glib/9966989#9966989). – hmjd Aug 31 '12 at 09:04
  • Moving the `-l*` flags to the end solved this problem, but then the compiler was complaining that it couldn't find the dependencies to libmat.so. Adding also the flag `-Wl,-rpath /usr/local/MATLAB/R2011a/bin/glnxa64` did the trick - now my program compiles and runs (with a segfault ;) )! Thanks a lot! – Tomas Aschan Aug 31 '12 at 09:42
  • @TomasLycken, no problem. Good luck with the segfault. – hmjd Aug 31 '12 at 09:45