【发布时间】: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的工作原理,因为我上次一定误解了一些东西。 -
取决于您阅读的内容。我想大多数作家都不会费心去报道这些东西。据我所知,即使是文档也没有明确提及。
-
未定义符号表示源代码中或您要链接的目标文件之一中不存在的符号。这包括导入库。这篇文章继续解释如何为您的可执行文件创建一个导入库,就像您的自我回答一样,尽管作者声称这“有点麻烦”,原因我无法理解。