使用 MinGW 编译为带有一些未定义引用的 .dll

Vor*_*ico 2 c++ windows dll mingw

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

void bar();

__declspec(dllexport)
void foo() {
    bar();
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Vor*_*ico 6

我想出了如何用 MinGW 来做这件事。

通常,当链接 DLL 文件(例如plugin.dll)时,您将符号列表导出到libplugin.a,但在这种情况下,我实际上想将符号从主机可执行文件导出host.exelibhost.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