【问题标题】:Linking a MinGW library to a MSVC app with a C interface使用 C 接口将 MinGW 库链接到 MSVC 应用程序
【发布时间】:2021-08-29 09:19:48
【问题描述】:

我正在尝试链接到使用 Media Autobuild Suite 编译的 OpenAL soft 库,我从 Visual Studio 收到以下错误:

libopenal.a(source.cpp.o) : fatal error LNK1143: invalid or corrupt file: no symbol for COMDAT section 0xA

我的应用程序使用 C++ 并直接在 Visual Studio 2019 中编译(但是,使用 VS2017 工具集)。 OpenAL soft 使用 C++ 编写,但暴露了 C 接口,MAB Suite 使用 MinGW/gcc 编译并生成 libopenal.a 静态库文件。

我从诸如From MinGW static library (.a) to Visual Studio static library (.lib) 和How to use libraries compiled with MingW in MSVC? 等多个其他问题中了解到,由于名称修改,使用不同编译器编译的目标文件通常不与 C++ 兼容,但通常 与 C 链接兼容。因为 C 不使用名称修饰,并且因为 ABI(通常)依赖于操作系统,所以在同一平台上编译的具有 C 接口的库通常是兼容的。

尽管如此,我一直遇到链接器错误,即上面的LNK1143。我已经确认包含的标头使用extern "C" { 来提示C 链接,并且两个版本的目标平台(x64)是相同的。我还按照this answer 的建议链接到libgcc.a,并且没有收到任何链接器错误。

这是否意味着 C 接口通常跨编译器兼容的说法是不正确的? 或者这是它不起作用的特殊情况?如果是后者,什么可能导致链接失败?如果我重新编译为共享库 (dlls) 而不是静态库(即使我仍然使用 MinGW 的 .a 文件而不是 .lib),我的运气会更好吗?

我无法为我的主应用程序从 MSVC 更改编译器。我打算在未来使用更多来自 MAB 套件的库,所以如果可能的话,我更愿意使用 MinGW 来处理这些依赖项,因为我不想手动重新编译所有 70 多个库。

感谢任何帮助。提前致谢。

【问题讨论】:

  • 我认为你运气不好,请参阅:social.msdn.microsoft.com/Forums/vstudio/en-US/… 和 docs.microsoft.com/en-gb/windows/win32/debug/…。那个帖子很老了,但看起来什么都没有改变。也许是 some mingw 目标文件将链接但其他的情况。无论如何,这似乎是证据。
  • 你能用 MSVC 构建库吗?它似乎是一个 cmake 项目,并说它是作为一个仅限 Windows 的库开始的。
  • stackoverflow.com/questions/2529770/… 似乎涵盖了所提出的问题
  • @M.M 我已经在我的问题中提到了这个问题,我的经验与这些答案相冲突,这就是我感到困惑的原因。如果可能的话,我想继续使用 MinGW 作为库,因为 suite I'm using to compile it 还构建了我打算在未来使用的 70 多个其他依赖项,我不想手动重建它们。现在看起来这可能是不可能的
  • 是的,使用共享库它应该可以工作(我很确定这就是兼容的 C 接口的含义)。

标签: c++ c visual-c++ linker mingw


【解决方案1】:

混合编译器很棘手并且容易出现问题。

在一些非常简单的情况下它可能会起作用,但肯定有很多情况下你会遇到问题,例如:

  • 如果不同的组件使用不同的运行时库
  • 如果内存管理混合在一起(例如,忘记在 MSVC 中使用 free() 在 MinGW 中释放分配给 malloc() 的内存)
  • 在 C++ 中使用异常处理时

我的建议是使用相同的编译器(甚至是相同版本的编译器)。

具体来说,OpenAL 可以使用 MinGW-w64 构建。所以也许你应该研究一下,而不是从网上下载一些预构建的版本。

或者 - 更简单一些 - 使用 MSYS2 并使用它的 pacman 包管理器来获得它自己的 OpenAL MinGW-w64 构建。

【讨论】:

    【解决方案2】:

    我知道什么对我有用,所以我会分享。

    我无法像最初尝试的那样在编译器之间链接静态库。我的理解是,库中保存的允许链接时代码生成的额外信息是特定于编译器的。 Brecht Sanders's answer 概述了代码不兼容的几个可能原因。

    不过,我可以通过一些额外的步骤链接到共享库。

    使用相同的套件(请参阅问题),我编译为共享并得到libopenal.dll、libopenal.dll.a 和libopenal.def。在我的例子中,.def 文件是由套件生成的。根据this answer,您可以使用gcc生成.def文件:

    gcc -shared -o your_dll.dll your_dll_src.c -Wl,--output-def,your_dll.def

    尝试链接到libopenal.dll.a 仍然给我错误(我不知道确切原因,而且我已经丢弃了日志。)我所做的是从.def 文件生成.lib 文件。在 Visual Studio 的内置终端中:

    lib /machine:x64 /def:libopenal.def
    

    这在工作目录中生成了一个libopenal.lib 文件。链接到这个文件效果很好,我能够在运行时成功加载 dll。

    我已经用套件中的许多其他 MinGW 编译库测试了相同的方法,包括 libavformat、libavcodec、libavutil、libavdevice、swresample 和 swscale,到目前为止他们都工作了。

    有点令人费解,但它似乎对我来说效果很好,所以我希望这可以帮助其他有同样问题的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多