matlab mex 文件的共享库位置:

Posted

技术标签:

【中文标题】matlab mex 文件的共享库位置:【英文标题】:shared library locations for matlab mex files: 【发布时间】:2011-01-12 10:02:44 【问题描述】:

我正在尝试编写一个使用 libhdf5 的 matlab mex 函数;我的 Linux 安装提供了 libhdf5-1.8 共享库和头文件。但是,我的 Matlab 版本 r2007b 提供了 1.6 版本的 libhdf5.so。 (显然,Matlab .mat 文件引导 hdf5)。当我编译 mex 时,它在 Matlab 中出现了段错误。如果我将我的 libhdf5 版本降级到 1.6(不是长期选择),代码可以编译并运行良好。

问题:我该如何解决这个问题?如何告诉 mex 编译过程链接到 /usr/lib64/libhdf5.so.6 而不是 /opt/matlab/bin/glnxa64/libhdf5.so.0 ?当我尝试在编译中使用 -Wl,-rpath-link,/usr/lib64 执行此操作时,我收到如下错误:

/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../x86_64-pc-linux-gnu/bin/ld: warning: libhdf5.so.0, needed by /opt/matlab/matlab75/bin/glnxa64/libmat.so, may conflict with libhdf5.so.6
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status

    mex: link of 'hdf5_read_strings.mexa64' failed.

make: *** [hdf5_read_strings.mexa64] Error 1

确认。最后的手段是下载 hdf5-1.6.5 标头的本地副本并完成它,但这不是未来的证明(我将来会升级 Matlab 版本。)。有什么想法吗?

编辑:根据 Ramashalanka 的出色建议,我

A) 调用mex -v 以获取3 个gcc 命令;最后是链接器命令;

B) 使用-v 调用该链接器命令以获取collect 命令;

C) 调用 collect2 -v -t 和其余的标志。

我的输出的相关部分:

/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtbeginS.o
hdf5_read_strings.o
mexversion.o
-lmx (/opt/matlab/matlab75/bin/glnxa64/libmx.so)
-lmex (/opt/matlab/matlab75/bin/glnxa64/libmex.so)
-lhdf5 (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libhdf5.so)
/lib64/libz.so
-lm (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libm.so)
-lstdc++ (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libstdc++.so)
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so)
/lib64/libpthread.so.0
/lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtendS.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crtn.o

所以,实际上来自/usr/lib64libhdf5.so 正在被引用。但是,我相信这会被环境变量 LD_LIBRARY_PATH 覆盖,我的 Matlab 版本会在运行时自动设置它,因此它可以找到自己的版本,例如libmex.so

我认为crt_file.c 示例在 b/c 中起作用,它不使用我正在使用的功能(H5DOpen,它在从 1.6 到 1.8 的移动中具有签名更改(是的,我正在使用 @ 987654336@)),或者,不太可能,b/c 它没有击中需要 hdf5 的 Matlab 内部部件。确认。

【问题讨论】:

在您的输出中,我看到 lib64/libhdf5.so 这是一个动态库。您需要指定静态库的显式路径(带有 .o 后缀),而不是使用 -lhdf5。如果仍然无法正常工作,则发布新的链接器输出。如果.so 文件是列表中唯一的一个,那么它就是唯一包含的一个。 LD_LIBRARY_PATH 或任何其他路径,例如-L,如果您没有 -lhdf5 作为选项并且明确指定静态库的路径(见下文),则无关紧要。我同意 h5_crtfile.c 上的 cmets,但我们需要的所有信息都在上面的链接器输出中。 我没有libhdf5.o 文件; gentoo 的 hdf5 包提供了libhdf5.solibhdf5.alibhdf5.la,以及一些fortran 和cpp 文件。我必须自己编译 libhdf5 吗?这是一个选项... 抱歉,我指的是.a,而不是.o。您可以通过例如检查您拥有的 libhdf5.a 文件是否是正确的版本。 strings libhdf5.a。我看到HDF5 Version: 1.8.4 在我的。如果您无法将正确的静态库作为二进制文件获取,则很容易编译。在下面查看我的 cmets 到您的其他查询。 strings /usr/lib64/libhdf5.a | grep 'library version' 给出输出“HDF5 库版本:1.8.4 HDF5 库版本:1.8.4 ...”由于某种原因,我无法链接到静态库。关于-fPIC的同样警告 好的。我发现如果我关闭 -bundle 会出现同样的 undefined reference to 'main' 错误。因此,当您调用 mex 时,您的系统上需要相当于 -bundle。从手册看来,-fPIC(或-fpic)是CFLAG,(可能)-sharedLDFLAG。是的,您的标头和库 do 似乎是正确的版本。我怀疑您是否需要重新编译 hdf5-fPIC,因为在我的系统上使用 -bundle 一切正常。 【参考方案1】:

以下在我的系统上工作:

    安装 hdf5 版本 1.8.4(你已经这样做了:我安装了源代码并编译以确保它与我的系统兼容,我得到 gcc 版本并且我得到静态库 - 例如为我的系统提供的二进制文件是 icc 特定的)。

    制作一个目标文件。你已经有了自己的文件。我使用了来自here 的简单h5_crtfile.c(一个好主意,首先从这个简单的文件开始寻找警告)。我将 main 更改为 mexFunction 并使用通常的 args 并包含 mex.h

    指定要显式加载的静态 1.8.4 库(没有必要的-L 的完整路径)并且不要在LDFLAGS 中包含-lhdf5。包括一个-t 选项,这样您就可以确保没有加载动态hdf5 库。您还需要安装了zlib-lz。对于 darwin,我们还需要 -bundle in LDFLAGS:

    mex CFLAGS='-I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -bundle' h5_crtfile.c -v
    

    对于 linux,您需要一个等效的与位置无关的调用,例如fPIC 可能还有-shared,但是我没有带matlab license 的linux 系统,所以无法检查:

    mex CFLAGS='-fPIC -I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -shared' h5_crtfile.c -v
    

    运行h5_crtfile mex 文件。这在我的机器上运行没有问题。它只是执行 H5Fcreate 和 H5Fclose 以在当前目录中创建“file.h5”,当我调用 file file.h5 时,我得到 file.h5: Hierarchical Data Format (version 5) data

请注意,如果我在上面的第 3 步中包含-lhdf5,那么当我尝试运行可执行文件时,matlab 会中止(因为它随后使用 matlab 的动态库,对我来说是 1.6.5 版),所以这肯定是解决我的系统上的问题。

感谢您的提问。我上面的解决方案对我来说肯定比我以前做的要容易得多。希望以上内容对您有用。

【讨论】:

嗯。当我尝试这个时,编译失败 b/c libmat.so 依赖于 libhdf5.so。那里有些奇怪。不幸的是,我不能包含 mex.h 而不同时拉入 Mathworks 的 hdf5;很遗憾,Mathworks 分发的头文件中不包含hdf5.h 好的,我已经重写了帖子,看看情况如何。 我用 mex 吐出的 gcc 命令在 shell 中编译。所以我尝试了你的解决方案,跳过了第 2 步和第 3 步; (-bundle 是达尔文特有的,顺便说一句)使用h5_crtfile.c,我得到“警告!此应用程序包含的 HDF5 头文件与此应用程序链接到的 HDF5 库使用的版本不匹配。数据损坏或分段如果应用程序继续,可能会出现故障。设置了“HDF5_DISABLE_VERSION_CHECK”环境变量,应用程序将继续。标题为 1.8.4,库为 1.6.5" 但是,file.h5 已创建!但是,在我的 mex 上使用这个技巧,它仍然存在段错误。 这是有用的信息:我没有收到关于 h5_crtfile.c 的任何警告,而且警告非常清楚。因此,在您的系统上,它必须在某处找到 1.6.5 版本的库。当您执行链接时(即第三个 gcc 调用“由 mex 吐出”),请使用 -v 执行此操作,并查看显示另一个 libhdf5* 的“库搜索路径”。确保路径中有 no 动态 hdf5 库(例如,您为什么跳过第 2 步?),否则 matlab 将在运行时采用它自己的 (1.6.5) 动态库。您确定您尝试链接的 static 库是 1.8.4,对吗? 文本“警告!HDF5 标头等”不会出现在 Matlab 窗口中,而是出现在调用 Matlab 的 shell 中。 (我认为它实际上是通过管道传输到 stderr 的)。这可能是为什么你没有看到它?根据您的建议,仍在为此努力...【参考方案2】:

我接受 Ramashalanka 的回答,因为它引导我找到了确切的解决方案,我将在此处发布只是为了完整性:

    从hdf5网站下载hdf5-1.6.5库,并将头文件安装到本地目录; 告诉 mex 在此本地目录中查找“hdf5.h”,而不是在标准位置(例如 /usr/include。) 告诉 mex 编译我的代码和 matlab 提供的共享对象库,并且不要LDFLAGS 中使用-ldfh5 标志。

我使用的命令本质上是:

/opt/matlab/matlab_default/bin/mex -v CC#gcc CXX#g++ CFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include" CXXFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include " -O -lmwblas -largeArrayDims -L/usr/lib64 hdf5_read_strings.c /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0

这被 mex 翻译成命令:

gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG hdf5_read_strings.c
gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG /opt/matlab/matlab75/extern/src/mexversion.c
gcc -O -pthread -shared -Wl,--version-script,/opt/matlab/matlab75/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -o hdf5_read_strings.mexa64  hdf5_read_strings.o mexversion.o  -lmwblas -L/usr/lib64 /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0 -Wl,-rpath-link,/opt/matlab/matlab_default/bin/glnxa64 -L/opt/matlab/matlab_default/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++

这个解决方案应该适用于我所有的各种目标机器,至少在我升级到 matlab r2009a 之前,我相信它使用 hdf5-1.8。感谢所有的帮助,很抱歉对此如此密集——我认为我过度致力于使用 hdf5 的打包版本,而不是一组本地头文件。

请注意,如果 Mathworks 在 Matlab 发行版中提供了一组头文件,这一切都将是微不足道的......

【讨论】:

这就是我处理需要链接 boost-thread 的多线程 mex 文件的方式。但是必须有某种方法让它链接到系统库而不是 Matlab 内部的库,并避免这种方式的段错误。被 Matlab 内部的任何提升所困扰并不是很好。 关于 Ramashalanka 的有用建议,我也可以说,在我的 boost-thread 链接情况下,我必须在 Linux 中而不是在 Mac 中执行此解决方法;在 Mac 中,mex 命令似乎不像在 Linux 中那样链接到内部版本。 类似于此处的答案:***.com/questions/9927568/… 可能会起作用(尽管问题是针对某些不同的东西)。如果我得到它的工作,我会报告。

以上是关于matlab mex 文件的共享库位置:的主要内容,如果未能解决你的问题,请参考以下文章

未找到 Mexopencv mex 文件

犰狳 + Matlab Mex 段错误

如何更新 Matlab 共享库?

将具有外部依赖项的共享库集成到 MATLAB |即犰狳、LAPACK、BLAS

Linux 环境下 动态库(共享库) 共享路径设置

MATLAB Mex 套接字包装库