Question

I have next situation: I need to create widget in standalone static library, which then will be linked with final application (visual c++ 9.0, qt 4.5). This static widget library contains some resources (icons), and consist of a several .cpp files (each contains standalone widget). As far as I know, i must initialize qt resource system, if i use them (resources) in static library, with call to "Q_INIT_RESOURCE( resource_file_name )". I solved this with next code (in every .cpp file in static library):


#include <QAbstractButton>

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

// ... widget code ....

Instead of my first approach, I have created separate init.cpp file in static library project with initialization code (to avoid including initialization code in every .cpp file), but this didn't work.

Why this didn't work ?

Is this approach with StaticLibInitializer is safe and portable among various compilers and platforms ?

Was it helpful?

Solution

It didn't work because you managed to get hit by static initialization order fiasco.

You can't move your code that initializes static objects outsize the translation unit (you can read it as source file) where these static objects are used. Not the way you did it. If you want to use the scheme you are using to initialize these static objects than move only declarations to your init.hpp header but leave instatiations StaticLibInitializer staticLibInitializer; in each file which uses static objects.
Above advice assumes each widget uses only its own resources. If you have situation in which one widget's resources are used by another widget you run into static initialization order fiasco again. You can manage this situation by using code like this

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

    StaticLibInitializer()
    {
         initialize();
    }
}

to make sure multiply instantiations of StaticLibInitializer will initialize given resource only once and then instantiate StaticLibInitializer for every resource you are going to use in given translation unit.

OTHER TIPS

The Q_INIT_RESOURCE macro can't be used in a namespace.

Let me quote from the qt manual: "Note: This macro cannot be used in a namespace. It should be called from main()". And even it gives you an example how to do it right, if this is not possible:

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

    namespace MyNamespace
    {
     ...

     void myFunction()
     {
         initMyResource();
     }
  }

Please look yourself why and how exactly it fails or does not fail if you use it in an unspecified way. The relevant code is in QtCore.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top