开发者

How to call Matlab from C++ code?

I am trying to call Matlab functions from C++ code.

With Matlab it comes an example of such code at /extern/examples/eng_mat/engdemo.cpp, however I found no way to build that source code.

Here is the makefile I use:

CFLAGS = -Wall -O3

INCLUDES = -I/opt/Matlab-2009a/extern/include

LIBRARIES = -Wl,-R/opt/Matlab-2009a/bin/glnx86 -L/opt/Matlab-2009a/bin/glnx86 -lmx -lmat -leng

out : engdemo.cpp
    g++ $(CFLAGS) $(INCLUDES) -static $^ $(LIBRARIES) -o out

clean :
    rm -f out

(Here /opt/Matlab-2009a is my Matlab root.) I am getting a linker error like this:

/usr/bin/ld: cannot find -lmx
collect2: ld returned 1 exit status
make: *** [out] Error 1

And the question is: how can I make g++ to compile engdemo.cpp ?

Note, that the shared library exists:

$ locate libmx.so
/opt/Matlab-2009a/bin/glnx86/libmx.so
/opt/Matlab-2009a/bin/glnx86/libmx.so.csf

and

$ ldd /opt/Matlab-2009a/bin/glnx86/libmx.so
    linux-gate.so.1 =>  (0x004b4000)
    libut.so => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libut.so (0x0078f000)
    libmwfl.so => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libmwfl.so (0x00110000)
    libicudata.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicudata.so.38 (0xb7f82000)
    libicuuc.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicuuc.so.38 (0x00bee000)
    libicui18n.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicui18n.so.38 (0x001f7000)
    libicuio.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicuio.so.38 (0x00e1c000)
    libz.so.1 => /usr/lib/libz.so.1 (0x0098e000)
    libstdc++.so.6 => /opt/Matlab-2009a/bin/glnx86/../../sys/os/glnx86/libstdc++.so.6 (0x00531000)
    libm.so.6 => /lib/libm.so.6 (0x00194000)
    libgcc_s.so.1 => /opt/Matlab-2009a/bin/glnx86/../../sys/os/glnx86/libgcc_s.so.1 (0x00eaa000)
    libpthread.so.0 => /lib/libpthread.so.0 (0x00900000)
    libc.so.6 => /lib/libc.so.6 (0x00345000)
    librt.so.1 => /lib/librt.so.1 (0x00964000)
    libdl.so.2 => /lib/libdl.so.2 (0x0014e000)
    libexpat.so.1 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libexpat.so.1 (0x00152000)
    libboost_thread-gcc42-mt-1_36.so.1.36.0 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libboost_thread-gcc42-mt-1_36.so.1.36.0 (0x00fc2000)
    libboost_signals-gc开发者_如何学Cc42-mt-1_36.so.1.36.0 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libboost_signals-gcc42-mt-1_36.so.1.36.0 (0x0017d000)
    libboost_system-gcc42-mt-1_36.so.1.36.0 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libboost_system-gcc42-mt-1_36.so.1.36.0 (0x00a06000)
    /lib/ld-linux.so.2 (0x001db000)

So, how can I make g++ to compile engdemo.cpp ?


Assuming $MATLABROOT is the path to MATLAB:

$MATLABROOT/bin/mex -f $MATLABROOT/bin/engopts.sh engdemo.cpp

If you add the -v switch, the verbose output will show you what commands are being used to compile the engine application.


Why are you compiling with -static? From "man gcc":

-static On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect.

In other words, the -static option forces the linker to only consider static libraries, meaning that it will try to find libmx.a rather than libmx.so. Since Matlab only ships with shared (dynamic) libraries, it fails.

Try removing that option & see what happens.

If that doesn't work, you may need to run libtool to help it find the .so's at runtime.


I thought I'd post something that related that might be of use to someone who stumbles upon this post in the future, on the theme of calling a Matlab function from C++.

In a tutorial posted on the Mathworks site the use of shared libraries is demonstrated for calling Matlab function(s) from a C++ file. Here, the mcc command is used to create a shared library.

Subsequently, the mbuild command is used to build the executable. However, if you have a complicated C++ code, which itself needs its own set of shared libraries for compilation, mbuild won't work. The tutorial doesn't demonstrate what needs to be done in this case. So, the purpose of my reply is to post that solution. The user C++ file is vigenere.cpp, and the shared library to be linked in this case is libvigenere.so, and this is the resultant call to g++:

g++ -o vigenere -L/usr/local/MATLAB/R2013b/runtime/glnxa64 -L. -I/usr/local/MATLAB/R2013b/extern/include/ vigenere.cpp -lmwmclmcrrt -lm -lvigenere

Some prerequisites:

  1. The Matlab Compiler Runtime (MCR) needs to be installed. Either type mcrinstaller at the Matlab prompt, or download the appropriate installer from the Matlab site.
  2. After doing this, make sure to set your LD_LIBRARY_PATH as per the instructions at the end of the installer.
  3. The current working directory needs to be added to the LD_LIBRARY_PATH. In bash, I do this by export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD

Note that 1&2 are also described in a readme.txt file generated by the mcc command.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜