Инициализация ресурсов qt, встроенных в статическую библиотеку

StackOverflow https://stackoverflow.com/questions/1392863

Вопрос

У меня есть следующая ситуация:Мне нужно создать виджет в автономной статической библиотеке, который затем будет связан с конечным приложением (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 безопасным и переносимым среди различных компиляторов и платформ ?

Это было полезно?

Решение

Это не сработало, потому что ты умудрился попасть под фиаско порядка статической инициализации.

Вы не можете переместить свой код, который инициализирует статические объекты, за пределы единицы перевода (вы можете прочитать ее как исходный файл), где используются эти статические объекты.Не так, как ты это сделал.Если вы хотите использовать схему, которую вы используете для инициализации этих статических объектов, переместите только объявления в свой заголовок init.hpp, но оставьте установки StaticLibInitializer staticLibInitializer; в каждом файле, который использует статические объекты.
Приведенный выше совет предполагает, что каждый виджет использует только свои собственные ресурсы.Если у вас возникла ситуация, в которой ресурсы одного виджета используются другим виджетом, вы снова сталкиваетесь с фиаско порядка статической инициализации.Вы можете справиться с этой ситуацией, используя подобный код

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

    StaticLibInitializer()
    {
         initialize();
    }
}

чтобы убедиться, что многократные экземпляры StaticLibInitializer инициализируют данный ресурс только один раз, а затем создают экземпляр StaticLibInitializer для каждого ресурса, который вы собираетесь использовать в данной единице перевода.

Другие советы

Макрос Q_INIT_RESOURCE не может быть использован в пространстве имен.

Позвольте мне процитировать из руководства по qt:"Примечание:Этот макрос не может быть использован в пространстве имен.Он должен быть вызван из main()".И даже это дает вам пример, как сделать это правильно, если это невозможно:

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

    namespace MyNamespace
    {
     ...

     void myFunction()
     {
         initMyResource();
     }
  }

Пожалуйста, посмотрите сами, почему и как именно он выходит из строя или не выходит из строя, если вы используете его неуказанным способом.Соответствующий код находится в QtCore.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top