如何从C++代码中调用Matlab?

3
我将尝试从C++代码中调用Matlab函数。
Matlab提供了一个这样的代码示例,位于/extern/examples/eng_mat/engdemo.cpp,但我找不到构建该源代码的方法。
以下是我使用的makefile:
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

(这里 /opt/Matlab-2009a 是我的 Matlab 根目录。)我遇到了以下链接器错误:

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

问题是:我如何让g++编译engdemo.cpp?

请注意,共享库已经存在:

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

并且

$ 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-gcc42-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)

那么,我该如何让g++编译engdemo.cpp?

1
确保这个工作:http://www.mathworks.com/support/solutions/en/data/1-1BSZR/?solution=1-1BSZR,在MEX调用中添加-v选项。这应该显示gcc/g++调用的所有命令行选项。您可能会在Makefile条目中获取信息。 - Ashish Uthama
3个回答

2
假设$MATLABROOT是MATLAB的路径:
$MATLABROOT/bin/mex -f $MATLABROOT/bin/engopts.sh engdemo.cpp

如果您添加了-v开关,详细输出将向您显示用于编译引擎应用程序的命令。


感谢您的回答,特别是提到了-v选项。 - Vahagn

0

我想发布一些相关的内容,可能对未来偶然发现这篇文章的人有所帮助,主题是如何从C++中调用Matlab函数。

在Mathworks网站上发布的教程中演示了使用共享库调用Matlab函数的方法。在这里,使用mcc命令创建共享库。

随后,使用mbuild命令构建可执行文件。但是,如果您有一个复杂的C++代码,它本身需要自己的一组共享库进行编译,那么mbuild将无法工作。该教程没有演示在这种情况下需要做什么。因此,我的回复的目的是发布解决方案。用户C++文件是vigenere.cpp,在这种情况下要链接的共享库是libvigenere.so,这是对g++的结果调用:

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

一些前提条件:

  1. 必须安装Matlab编译器运行时(MCR)。在Matlab提示符下键入mcrinstaller,或从Matlab site下载适当的安装程序。
  2. 完成此操作后,请根据安装程序末尾的说明设置您的LD_LIBRARY_PATH
  3. 需要将当前工作目录添加到LD_LIBRARY_PATH中。在bash中,我通过export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD来实现这一点。

请注意,1和2也在由mcc命令生成的readme.txt文件中描述。


0

为什么你要使用-static编译?从"man gcc"中可以看到:

-static 在支持动态链接的系统上,这会防止与共享库链接。在其他系统上,此选项无效。

换句话说,-static选项强制链接器只考虑静态库,这意味着它将尝试查找libmx.a而不是libmx.so。由于Matlab只提供共享(动态)库,因此会失败。

尝试删除该选项并查看发生了什么。

如果这样做不起作用,您可能需要运行libtool来帮助它在运行时找到.so文件。


感谢您的回答。那里的-static选项是复制粘贴makefile的副作用 : )。您是完全正确的,删除该选项可以使代码编译。然而,正如SCFrench的答案所示,应该传递几个-D(宏定义)选项给g++。 - Vahagn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接