如何在 Windows 上使用 Visual C++ 强制加载链接库

Posted

技术标签:

【中文标题】如何在 Windows 上使用 Visual C++ 强制加载链接库【英文标题】:How to force a linked library to load using Visual C++ on Windows 【发布时间】:2015-03-11 21:50:51 【问题描述】:

我正在尝试处理具有多个动态库的项目,在库中创建了一些全局对象并在列表中注册,以便可执行文件可以使用它们来构建其他东西。在可执行文件中没有对任何库的任何函数的引用,它只需要对象,然后它就知道要做什么。这些库旨在像在链接时选择的插件一样工作。

理想情况下,在编译ExecutableProject 时,我链接LibraryA,会创建一个A 类型的对象(通过在库中编译的一些代码),ExecutableProject 会因此而做事,使用LibraryA 中的函数.相反,如果我链接LibraryB,则会创建B 类型的对象并发生其他事情。

问题是,由于 ExecutableProject 没有直接使用库中的任何函数或类,所以没有加载库,也永远不会创建对象。

我找到了一些解决方法:

    我可以在编译ExecutableProject 时在链接时使用/INCLUDE:symbol,其中符号是在LibraryALibraryB 中导出的任何符号。我不喜欢这样,因为我必须知道库中函数的修饰名称,这并不总是可用的。此外,它并不优雅。 我可以使用虚拟变量。我可以将__declspec(dllexport) int force_link_A_or_B; 放入LibraryALibraryB__declspec(dllimport) extern int force_link_A_or_B; 放入ExecutableProject。我不喜欢这样,因为如果我有更多的库,我必须为每个库添加一个变量。基本上ExecutableProject中的代码虽然不知道会链接哪些库,但还是需要知道有多少个库可以链接在一起。

在 Linux 上,使用 gcc 和 ld,很容易解决这个问题,只需要一个简单的链接器标志 -Wl,--no-as-needed。有没有办法使用 Visual Studio 做到这一点?如果有像/INCLUDE 这样工作但使用整个库而不是符号并且不需要修饰名称的东西,我会很高兴。

谢谢

编辑:我被要求澄清这种设计的工作原理。理想情况下,当我编译ExecutableProject 时,我链接LibraryAB 并创建一个对象。

`ClassA A;`

这被放置在在LibraryA 中编译的源文件中的所有函数之外。同样的事情发生在LibraryB。这里的关键是ClassAClassB 继承自BaseClassExecutableProject 很清楚。创建对象时,BaseClass 构造函数运行,并在其中保存指向this(因此是派生对象)的BaseClass* 指针,ExecutableProject 使用该指针。它不需要知道派生类的任何信息,因为它只使用一个BaseClass 指针,但是当它从中调用虚函数时,会根据所指向对象的实际类型执行不同的函数。如果有更多对象而不是只有两个选项,我会将BaseClass 指针保存在列表或映射中,并让ExecutableProject 访问它。

【问题讨论】:

您真的需要在编译期间将您的 DLL 引用添加到可执行文件中吗?这很不寻常。 您的问题似乎自相矛盾。一方面,“在可执行文件中没有引用任何库的任何函数”。另一方面,“并且 ExecutableProject 使用 LibraryA 中的函数来做事。”那么您是否使用库中的函数?如果你不这样做,那么图书馆的目的是什么?你能展示一些代码来展示你的设置吗?这对我来说毫无意义。 I don't like this because I have to know the decorated name of a function in the library 使用 .def 文件导出一个具有普通、未修饰名称的符号。 @CollinDauphinee 显然链接器忽略了“未使用”的库。 @IgorTandetnik ExecutableProject 知道该怎么做,因为在库中创建了一些静态对象并在地图中注册。我将通过澄清更新问题。 【参考方案1】:

不要尝试这个。设计存在根本缺陷。

特别是,由于您没有对 DLL 进行任何显式调用,因此您将仅依赖通过对 DllMain 的隐式调用创建的对象 A

但是在 Windows 规则下,你被禁止在 DllMain 中或从 DllMain 中做任何有趣的事情,所以对象 A 不会很有用。

【讨论】:

谢谢。您能否进一步澄清您的信息?我同意这种设计过于复杂,但我认为它可以工作。请检查我对我的问题的编辑,这进一步解释了项目的工作原理。真正重要的是A 存在。 我有同样的问题,但我的情况不同:我将 exe 文件与 dll 链接,它从 exe 文件向全局对象注入东西(我使用 Qt 框架,我使用 qApp 全局实例来改变一些东西)。并且由于“未使用”而未加载dll文件,因此我没有得到我需要的东西。

以上是关于如何在 Windows 上使用 Visual C++ 强制加载链接库的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 7 上使用 Vim 的“make”命令和 Visual Studio 的编译器编译 C 程序?

如何在Visual C ++中创建非托管Windows GUI?

在 WSL@Windows 10 上使用 C-v 的 Vim 中的 Visual-Block 模式不起作用

如何在未安装Visual Studio的计算机上安装Windows服务?

如何使用 Visual Studio 2017 在 Windows 上构建 OpenSSL?

如何在 Windows 上使用 Visual C++ 强制加载链接库