13

我有下一个情况:我需要在独立静态库中创建小部件,然后将其与最终应用程序(visual c++ 9.0,qt 4.5)链接。这个静态小部件库包含一些资源(图标),并由几个 .cpp 文件组成(每个文件都包含独立的小部件)。据我所知,如果我在静态库中使用它们(资源),我必须初始化 qt 资源系统,并调用“Q_INIT_RESOURCE(resource_file_name)”。我用下一个代码解决了这个问题(在静态库中的每个 .cpp 文件中):


#include <QAbstractButton>

namespace {
struct StaticLibInitializer
{
    StaticLibInitializer()
    {
        Q_INIT_RESOURCE(qtwidgets_custom_resources);
    }
};
StaticLibInitializer staticLibInitializer;
} 

// ... widget code ....

我没有使用第一种方法,而是在静态库项目中使用初始化代码创建了单独的 init.cpp 文件(以避免在每个 .cpp 文件中包含初始化代码),但这不起作用。

为什么这不起作用?

这种使用 StaticLibInitializer 的方法在各种编译器和平台之间是否安全且可移植?

4

2 回答 2

11

它不起作用,因为您设法被静态初始化命令 fiasco击中。

您不能移动初始化静态对象的代码,使其超出使用这些静态对象的翻译单元(您可以将其作为源文件读取)。不是你做的那样。如果你想使用你用来初始化这些静态对象的方案,而不是只将声明移动到你的 init.hpp 标头,但StaticLibInitializer staticLibInitializer;在每个使用静态对象的文件中留下 instatiations。
以上建议假定每个小部件仅使用自己的资源。如果您遇到一个小部件的资源被另一个小部件使用的情况,您会再次遇到静态初始化命令失败。您可以使用这样的代码来管理这种情况

StaticLibInitializer
{
    void initialize()
    {
        static Q_INIT_RESOURCE(qtwidgets_custom_resources);
    }

    StaticLibInitializer()
    {
         initialize();
    }
}

确保 StaticLibInitializer 的多个实例化只会初始化给定资源一次,然后为您将在给定翻译单元中使用的每个资源实例化 StaticLibInitializer。

于 2009-09-14T08:11:45.607 回答
8

Q_INIT_RESOURCE 宏不能在命名空间中使用。

让我引用 qt 手册:“注意:此宏不能在命名空间中使用。它应该从 main() 调用”。甚至它还为您提供了如何正确执行此操作的示例,如果这是不可能的:

  inline void initMyResource() { Q_INIT_RESOURCE(myapp); }

    namespace MyNamespace
    {
     ...

     void myFunction()
     {
         initMyResource();
     }
  }

如果您以未指定的方式使用它,请看看自己为什么以及它究竟如何失败或不失败。相关代码在 QtCore 中。

于 2009-09-08T09:25:47.570 回答