如何在静态链接库中强制构建全局对象?[MSVC9],

3
我有一个全局函数指针列表,需要在启动时填充。顺序并不重要,也没有会使静态初始化复杂化的依赖关系。为了方便,我编写了一个类,在其构造函数中添加单个条目到该列表中,并通过宏在必要的地方分散全局实例化这个类。该方法的主要目标之一是消除外部明确引用每个此类实例的需求,而是允许需要在列表中注册内容的每个文件独立进行操作。看起来很整洁。
然而,当将这些对象放置在静态库中时,链接器会丢弃(或者从未链接进来)这些单元,因为它们中没有任何代码被明确引用。在编译单元中明确引用符号将是逆生产的,直接违反了该方法的主要目标之一。出于相同的原因,/INCLUDE 不是可接受的选项,/OPT:NOREF 与此问题实际上无关。
Metrowerks 有一个 __declspec 指令,GCC 有 -force_load,但我找不到 MSVC 的等效方法。
2个回答

0
如果您不想#include任何内容,那么这将无法起作用,但如果您可以接受这一点,一种常见的技术是使用一个nifty-counter来调用在main函数之前声明的cpp文件中的函数,该函数将初始化该文件中的任何静态对象。
我在需要将许多对象放入工厂的项目中使用了这个方法。我们必须有一个文件#include每个声明必须在工厂中注册自己的类的头文件。我认为这是可以做到的,因为我强烈倾向于编写源文件,而不是设置各种链接器/编译器选项。
另一种方式(似乎不能通过静态库实现,请参见注释)可以将某些内容声明为__declspec(dllexport),这将强制包含它(__declspec也适用于可执行文件)。

主要目的是避免在文件之外的任何地方引用全局对象。如果有帮助的话,这是为了一个单元测试框架;我非常讨厌在同一位置引用来自多个库的每个单元测试的想法,而且随着单元测试数量的增加,它的扩展性非常差。不幸的是,__declspec(dllexport) 对于静态库无效,因为它不是 DLL。 - Peter C O Johansson
谢谢澄清。嗯,我原以为当库被包含到操作系统加载的实际模块(dll/exe)中时,__declspec才会发挥作用,但显然我错了。 - Macke

0

我认为你需要在这些变量声明周围使用#pragma optimize("", off)#pragma optimize("", on)对。这将关闭优化,以免丢弃它们。

另外请记住,预处理器指令不能成为宏的一部分。__pragma可用于某些事情(并专门设计用于在宏中使用),但不是所有事情,而且语法略有不同。不确定它是否适用于优化。


尝试过了,但是没有任何效果。 - Alan Baljeu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接