【问题标题】:Compile to .dll with some undefined references with MinGW使用 MinGW 编译为带有一些未定义引用的 .dll
【发布时间】:2017-02-07 02:46:54
【问题描述】:

我在某处听说所有 Windows .DLL必须包含它引用的每个符号的定义,所以像这样的 .DLL 文件永远不会编译,因为它没有实现 bar()。

void bar();

__declspec(dllexport)
void foo() {
    bar();
}

我认为类比是 .DLL 本质上是具有不同入口点的可执行文件,因此它们必须定义所有引用,就像可执行文件一样。

但在 Unix 环境中,我可以毫无问题地将其编译为 .so 文件。然后我可以使用主机应用程序中的dlopen(path, RTLD_NOW | RTLD_GLOBAL); 来加载库并将主机的符号与库的符号合并。如果宿主定义了bar(),库将简单地调用该函数。

我不能只是将所有内容重新定义到 .DLL 文件中,因为在我的应用程序中,该库使用来自主机的数千个符号。使用 MinGW 或可能的 Visual C++,真的没有办法通过在 .DLL 中未定义并在加载时合并它来使用来自主机的符号吗?我也不想在 .DLL 中设置数千个回调函数,因为 C++ 方法很难做到这一点。

【问题讨论】:

  • 你听错了。 Windows DLL 可以使用加载它的可执行文件中的符号,尽管这有点不寻常。您只需从可执行文件中导出函数(例如,使用 __declspec(dllexport))并将其导入 DLL(例如,使用 __declspec(dllimport))。
  • ...虽然现在想起来,但不知道MinGW是否支持这样做。我不明白为什么它不会,但我不知道。
  • 如果需要,我愿意使用 Visual C++,但我很高兴这是可能的。我正在重读dllimport 的工作原理,因为我上次一定误解了一些东西。
  • 取决于您阅读的内容。我想大多数作家都不会费心去报道这些东西。据我所知,即使是文档也没有明确提及。
  • 未定义符号表示源代码中或您要链接的目标文件之一中不存在的符号。这包括导入库。这篇文章继续解释如何为您的可执行文件创建一个导入库,就像您的自我回答一样,尽管作者声称这“有点麻烦”,原因我无法理解。

标签: c++ windows dll mingw


【解决方案1】:

我想出了如何使用 MinGW 来做到这一点。

通常,在链接 DLL 文件时(例如 plugin.dll),您将符号列表导出到 libplugin.a,但在这种情况下,我实际上想将符号从主机可执行文件 host.exe 导出到 libhost.a .

x86_64-w64-mingw32-g++ -o host.exe host.cpp -Wl,--out-implib,libhost.a

这会生成符号列表,您可以在构建插件时链接到该列表。

x86_64-w64-mingw32-g++ -shared -o plugin.dll plugin.cpp -L. -lhost

这将使用libhost.a 文件(在当前目录“.”中)构建 DLL。

现在,用__declspec(dllexport) 填充您的主机代码有点烦人,因此您可以添加--export-all-symbols 链接器标志。 而且由于某种原因,这样做之后似乎也不需要_declspec(dllimport) 属性,但我不知道为什么。 所以,你可以用

编译主机

x86_64-w64-mingw32-g++ -o host.exe host.cpp -Wl,--export-all-symbols,--out-implib,libhost.a

【讨论】:

  • 参见stackoverflow.com/a/4490536/886887,__declspec(dllimport) 不是必需的,但允许链接器优化调用。 (虽然 MinGW 编译和链接在一个命令中,也许你也可以免费获得优化。)
  • 为了未来读者的利益,请注意导出所有符号而不是特定符号的(潜在)缺点是它意味着第三方插件可能使用您没有的内部符号或功能t 打算提供,可能会导致兼容性问题。如果您只处理自己的代码,这无关紧要 - 尽管在这种情况下,使用静态链接通常比使用 DLL 更简单。
  • 这是一个很好的解决方案。但是我真的觉得用mingw的windows构建DLL的方式很丑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 2013-06-03
相关资源
最近更新 更多