【问题标题】:Linking and LOADING static .lib with mex使用 mex 链接和加载静态 .lib
【发布时间】:2014-09-02 11:08:08
【问题描述】:

所以,我有一个调用我的 C 源代码的 MEX 网关脚本文件。我使用 -L 和 -I 命令将我的 64 位编译 GSL 库 (.libs) 链接到我的 mex 可执行文件,然后在 .mexw64 的扩展名下编译。

我希望将此可执行文件传输到另一台 Windows 机器并运行良好,而无需安装任何 GSL 库。这是唯一的解决方案,我不在乎他关于编译时动态链接/代码生成的好处的论点是什么。我想要一个可执行文件,它的每个功能不仅(当然)预先声明,而且还预先定义。

我被引导相信这就是“静态”链接与动态链接的区别;但我在互联网上阅读了一些相互矛盾的定义。我需要一个完全 100% 独立的单一文件。

假设您可以在我可以生成的 mex 函数中链接实际的 .obj 文件,但不幸的是,我得到了未解决的符号错误。

其他人提到我可以使用 -l(小写 L)直接静态链接所需的实际 .lib,但事实并非如此。

那么有没有人可以引导我朝着正确的方向前进,或者如何不仅链接所有内容,而且还链接定义并在可执行文件运行时准备好加载 - 完全独立,或者我为什么会遇到包含 .obj 文件时未解决的符号/链接器错误?我是否误解了有关链接过程的一些基本内容?

另外:为了详细说明,我通过 Visual Studio 为 64 位架构构建和链接了 GSL 库,我可以轻松地将它与 MATLAB 链接,所以这不是我的问题(不再)。

编辑:我在这里看到了帖子: Generating standalone MEX file with GNU compilers, including libraries

然而,这并不能解决我的问题,尽管它是同一个问题。我无权访问 gcc;它终于在 MATLAB 中的 MSVS12 编译器上进行编译,我不会尝试通过 MinGW 使用 GCC 重新编译(已经尝试过,无法弄清楚),所以 -static 和 .a 选项不可用。

【问题讨论】:

  • 您尝试过listing the .lib on the mex command line(即mex -v -largeArrayDims myMexfun.cpp libgsl.lib)吗?你确定你已经构建了 GSL 静态库,而不是生成 .lib 的 dll,而只是一个存根?
  • @chappjc: +1 这是一个问题,解释了链接到 DLL 的不同方式,以及导入库和静态库之间的区别:stackoverflow.com/q/3573475/97160

标签: matlab visual-c++ linker static-libraries mex


【解决方案1】:

在您的previous post 中,您提到您决定使用Brian Gladman 提供的VS 解决方案,使用Visual C++ 编译GSL 库。

这里是关于如何构建一个与 GSL 库静态链接的 MEX 函数的分步说明:

  1. 下载 GNU GSL 源代码 (GSL v1.16)
  2. 下载匹配的 Visual Studio 项目文件 (VS2012 for GSL v1.16)
  3. 解压 GSL 压缩包,告诉C:\gsl-1.16
  4. 解压源文件顶部的 VS 项目文件,这将覆盖三个文件并添加一个文件夹 C:\gsl-1.16\build.vc11
  5. 打开 Visual Studio 2012,加载解决方案:C:\gsl-1.16\build.vc11\gsl.lib.sln
  6. 将配置更改为所需的输出:对我来说,我选择了platform=x64mode=Release
  7. 首先您必须先构建gslhdrs 项目
  8. 现在构建整个解决方案。这将创建两个静态库cblas.libgsl.lib 存储在C:\gsl-1.16\lib\x64\Release 中(以及相应的PDB 调试符号)。它还将创建一个包含最终头文件的目录:C:\gsl-1.16\gsl

接下来我们继续构建一个 MEX 函数。采用以下简单程序(从 Bessel 函数计算一些值,并将其作为输出返回):

gsl_test.c

#include "mex.h"
#include <gsl/gsl_sf_bessel.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    if (nrhs != 0 || nlhs > 1) mexErrMsgTxt("Wrong number of args.");
    plhs[0] = mxCreateDoubleScalar(gsl_sf_bessel_J0(5.0));
}

这是在 MATLAB 中编译上述 C 代码的方法:

>> mex -largeArrayDims gsl_test.c -I"C:\gsl-1.16" -L"C:\gsl-1.16\lib\x64\Release" cblas.lib gsl.lib

最后我们测试 MEX 文件,并将其与 MATLAB 自己的 Bessel 函数报告的值进行比较:

>> x = gsl_test()
ans =
   -0.1776

>> y = besselj(0,5)
y =
   -0.1776

>> max(x-y)    % this should be less than eps
ans =
   8.3267e-17

请注意,构建的 MEX 函数没有外部 DLL 依赖项(除了预期的“Visual C 运行时”和通常的 MATLAB 库)。您可以根据需要使用Dependency Walker 进行验证。所以你可以简单地单独部署gsl_test.mexw64文件(假设用户已经在他们的机器上安装了相应的VC++ runtime)。

【讨论】:

  • +1 很好的说明。在构建 GSL DLL 时,Brian Gladman 的 gsl_hdrs.exe 程序在每个导出的对象声明上添加必要的 __declspec 属性是必不可少的(如果不是,则只需 extern)。 @user3145575 请注意,当您解压 VC11 项目 zip 时,它会用修补版本覆盖 3 个 GSL 文件。这些必要的更改记录在 gsl.vc11.changes.txt 中。
  • 对,当你构建gslhdrs项目时(上面说明中的第7步),它实际上会运行gslhdrs.exe程序作为构建后的步骤来收集所有头文件和补丁他们使用正确的extern 声明。
  • 再次感谢您,Amro。我设法让它全部编译并工作,我只是对静态库与动态dll与由dll等创建的存根库感到困惑;您对我的主要帖子的第二条评论对解决这个问题很有帮助
  • @user3145575 Amro 解决了这个问题很好,虽然并不意外。 ;) 当你有机会时,你应该投票赞成他的答案。祝你工作顺利。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-19
  • 1970-01-01
  • 1970-01-01
  • 2014-05-31
  • 1970-01-01
  • 2011-11-14
  • 2014-11-15
相关资源
最近更新 更多