我听说所有Windows .DLL 必须包含它引用的每个符号的定义,因此像这样的.DLL文件永远不会编译,因为它没有实现bar()
。 / p>
void bar();
__declspec(dllexport)
void foo() {
bar();
}
我认为类比是.DLL本质上是具有不同入口点的可执行文件,因此它们必须将所有引用定义为可执行文件。
但是在Unix环境中,我可以将它编译成.so文件,没有任何问题。然后我可以使用主机应用程序中的dlopen(path, RTLD_NOW | RTLD_GLOBAL);
来加载库并将主机的符号与库的符号合并。如果主机定义bar()
,则库将只调用该函数。
我不能只是将所有内容重新定义到.DLL文件中,因为在我的应用程序中,库使用来自主机的数千个符号。使用MinGW或可能的Visual C ++,是否真的没有办法使用主机中的符号,在.DLL中保留未定义并在加载时合并它?我也不想在.DLL中设置数千个回调函数,因为使用C ++方法会变得很困难。
答案 0 :(得分:3)
我想出了如何使用MinGW。
通常,在链接DLL文件(例如plugin.dll
)时,会将符号列表导出到libplugin.a
,但在这种情况下,我实际上想要从主机可执行文件中导出符号{{1转到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
文件(在当前目录“。”中)构建DLL。
现在,使用libhost.a
填充主机代码有点烦人,因此您可以添加__declspec(dllexport)
链接器标志。
出于某种原因,在执行此操作之后似乎不需要--export-all-symbols
属性,但我不知道为什么。
因此,您可以使用
_declspec(dllimport)