【发布时间】: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 知道该怎么做,因为在库中创建了一些静态对象并在地图中注册。我将通过澄清更新问题。
标签: c++ visual-c++ linker global-variables libraries