1

首先,我将展示我的问题,然后提供更多背景细节:

我的问题

  1. 在 DLL 模块中定义全局对象是个好主意吗?
  2. 无论如何,我应该如何确保在主机程序中调用 main() 函数之前构造 DLL 模块中的全局对象?

背景

我在Windows平台上的一个Visual C++项目中工作(但同时我们需要保证我们的源代码的跨平台能力以支持 Linux)。

我的一位同事被要求设计和实现一些可以由其他项目共享的独立 DLL 模块。他计划开发两个不同用途的DLL:

  1. DLL#1 - 一个接口管理器模块,看起来像一个简化的 COM。该 DLL 将包含一个管理实用程序类的所有工厂的 C++ 类。
  2. DLL#2 - 所有实用程序类及其相应工厂类的容器。

他对这种设计的考虑包括:

  1. COM 不是跨平台的。此外,COM 对我们的项目环境来说有点过于复杂,所以他设计了这个 Simplified COM 库。
  2. 他没有将所有东西都放在一个 DLL 中,因为他认为这个简化的 COM 库是非常独立的,不应该与诸如“XML 解析器”之类的实用程序类混合。我同意这一点。
  3. 所有实用程序类都有其相应的工厂类。我的同事在 DLL#2 的 .cpp 文件中为每个工厂类定义了一个全局对象,并编写了一些棘手的代码让它们注册到 Simplified COM 库。他的意图是:全局对象应该在宿主程序中的main()函数被调用之前构建,并在构建过程中将它们注册到简化的COM中,这样宿主程序就可以创建实用程序类的实例。进入main()。这种行为与 COM 非常相似。我同意这一点,但正如我在“我的问题”部分中提到的那样,我的问题也会出现。

事实上,通过一些实际测试,我们发现这些全局对象无法按意图构建,可悲的是,这让他心碎;-)。但我认为他的设计看起来仍然不错,所以我们想找出一些方法让它发挥作用。我们更愿意以这种方式使用这些 DLL:这些 DLL 与库和包含一起部署在开发人员的计算机中。然后在一个具体的 VC++ 项目中,它们在链接时被合并。现在我们没有编译或链接错误,只是 DLL #2 中的这些全局对象没有按需要创建。

4

1 回答 1

1

不能用DLL的DllMain()函数来初始化一切吗?只需检查DLL_PROCESS_ATTACH,它将让您知道 DLL 是否正在加载。同样,您可以使用它DLL_PROCESS_DETACH来执行任何清理。

如果你对 Linux 保持开放,你也可以使用 GCC 的__attribute__((constructor)).

至于你的问题:

  1. 在可执行文件中使用全局变量是一个好主意。这是否是一个“好”的想法完全是主观的。我个人尽可能避免使用全局变量,因为它可以简化事情(更少的意大利面条代码;将引用/对象作为参数传递使依赖关系清晰;更少的线程问题等)。我不能给出坚定的“是”或“否”,因为我不完全理解您的用例。一个例子会有所帮助。
  2. 我不明白为什么需要在main()函数之前创建它们。如果您可以保证它们是在 DLL 中创建的DllMain(),它将在 DLL 中的任何其他函数之前被调用(并且用户不调用它;操作系统会调用它),您还真的需要它之前main()吗?我会感到惊讶。
于 2012-11-25T16:22:41.930 回答