Pergunta

Eu tenho a próxima situação:Preciso criar um widget em uma biblioteca estática independente, que será vinculada ao aplicativo final (visual c++ 9.0, qt 4.5).Esta biblioteca de widgets estáticos contém alguns recursos (ícones) e consiste em vários arquivos .cpp (cada um contém um widget independente).Pelo que eu sei, devo inicializar o sistema de recursos qt, se eu usá-los (recursos) na biblioteca estática, com chamada para "Q_INIT_RESOURCE (resource_file_name)".Resolvi isso com o próximo código (em cada arquivo .cpp na biblioteca estática):


#include <QAbstractButton>

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

// ... widget code ....

Em vez da minha primeira abordagem, criei um arquivo init.cpp separado em um projeto de biblioteca estática com código de inicialização (para evitar incluir código de inicialização em cada arquivo .cpp), mas isso não funcionou.

Por que isso não funcionou?

Essa abordagem com StaticLibInitializer é segura e portátil entre vários compiladores e plataformas?

Foi útil?

Solução

Não funcionou porque você conseguiu ser atingido por fiasco da ordem de inicialização estática.

Você não pode mover seu código que inicializa objetos estáticos superando a unidade de tradução (você pode lê-lo como arquivo de origem) onde esses objetos estáticos são usados.Não do jeito que você fez.Se você quiser usar o esquema que está usando para inicializar esses objetos estáticos, mova apenas as declarações para o cabeçalho init.hpp, mas deixe as instanciações StaticLibInitializer staticLibInitializer; em cada arquivo que usa objetos estáticos.
O conselho acima pressupõe que cada widget usa apenas seus próprios recursos.Se você tiver uma situação em que os recursos de um widget são usados ​​por outro widget, você se deparará novamente com um fiasco de ordem de inicialização estática.Você pode gerenciar esta situação usando um código como este

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

    StaticLibInitializer()
    {
         initialize();
    }
}

para garantir que as instanciações multiplicadas de StaticLibInitializer inicializem determinado recurso apenas uma vez e, em seguida, instanciem StaticLibInitializer para cada recurso que você usará em determinada unidade de tradução.

Outras dicas

A macro q_init_resource não pode ser usada em um espaço para nome.

Deixe -me citar do manual QT: "Nota: esta macro não pode ser usada em um espaço para nome. Ele deve ser chamado de Main ()". E mesmo isso dá um exemplo de como fazê -lo certo, se isso não for possível:

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

    namespace MyNamespace
    {
     ...

     void myFunction()
     {
         initMyResource();
     }
  }

Veja -se por que e como exatamente isso falha ou não falha se você o usar de maneira não especificada. O código relevante está no qtcore.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top