【问题标题】:How to call Matlab from C++ code?如何从 C++ 代码调用 Matlab?
【发布时间】:2011-03-11 01:18:36
【问题描述】:

我正在尝试从 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 呢?

【问题讨论】:

标签: c++ matlab g++ shared-libraries linker-errors


【解决方案1】:

假设 $MATLABROOT 是 MATLAB 的路径:

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

如果添加 -v 开关,详细输出将显示正在使用哪些命令来编译引擎应用程序。

【讨论】:

  • 感谢您的回答,特别是提到 -v 选项。
【解决方案2】:

你为什么用-static 编译?来自“man gcc”:

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

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

尝试删除该选项,看看会发生什么。

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

【讨论】:

  • 感谢您的回答。那里的 -static 选项是复制粘贴makefile的副作用:)。您是绝对正确的,删除​​该选项会使代码编译。但是,正如 SCFrench 的回答所得出的那样,有几个 -D (宏定义)选项应该传递给 g++。
【解决方案3】:

我想我会以从 C++ 调用 Matlab 函数为主题,发布一些相关的内容,以供将来偶然发现这篇文章的人使用。

在 Mathworks 网站上发布的 tutorial 中,演示了使用共享库从 C++ 文件调用 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 执行此操作

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 2012-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多