如何在 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
,其中符号是在LibraryA
或LibraryB
中导出的任何符号。我不喜欢这样,因为我必须知道库中函数的修饰名称,这并不总是可用的。此外,它并不优雅。
我可以使用虚拟变量。我可以将__declspec(dllexport) int force_link_A_or_B;
放入LibraryA
和LibraryB
和__declspec(dllimport) extern int force_link_A_or_B;
放入ExecutableProject
。我不喜欢这样,因为如果我有更多的库,我必须为每个库添加一个变量。基本上ExecutableProject
中的代码虽然不知道会链接哪些库,但还是需要知道有多少个库可以链接在一起。
在 Linux 上,使用 gcc 和 ld,很容易解决这个问题,只需要一个简单的链接器标志 -Wl,--no-as-needed
。有没有办法使用 Visual Studio 做到这一点?如果有像/INCLUDE
这样工作但使用整个库而不是符号并且不需要修饰名称的东西,我会很高兴。
谢谢
编辑:我被要求澄清这种设计的工作原理。理想情况下,当我编译ExecutableProject
时,我链接LibraryA
或B
并创建一个对象。
`ClassA A;`
这被放置在在LibraryA
中编译的源文件中的所有函数之外。同样的事情发生在LibraryB
。这里的关键是ClassA
和ClassB
继承自BaseClass
,ExecutableProject
很清楚。创建对象时,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服务?