Qt: Load resources from static or shared library

Usually Qt resource file (.qrc) is embedded inside the main executable file for automatic access without any additional operation. Just compile and you have access to the resources from any point of the code by using the special path prefix required for the resource virtual file system. However, if required, is also possible to load resources from static or shared libraries with a minimal efforts.

Full project example can be found here

In the linked example there are two libraries, one shared and one static (called MySharedLibrary and MyStaticLibrary). Both libraries have an icon resource loaded and showed in the main window. Since Qt resources are converted into C++ code there is no difference with a standard C++ code, that's mean they can compiled inside the library without any limit (on the contrary, for example, Windows native resource system can be embedded only inside executable and dynamic libraries DLL, but not inside static libraries). The project file automatically connect the libraries to the main application than, for use these "external" resource, it's only needed to programmatically initialize them inside the Qt resource system engine. The macro for make this initialization is Q_INIT_RESOURCE() (official documentation here). As important point to keep in mind is the name of the resource file .qrc can not be the same but have to be different for both application and libraries, we'll see later the reasons. The macro can not be called inside namespace than the best point to call it is inside the main() function just before start execution of the application. It take as argument the name of the .qrc resource file you want to load. In short this macro "compose" and call a global function named with a fixed prefix and the name of the resource file param, something like functionprefix_resourcefilename(). This function initialize the resources and add them to Qt resource system to be called from code.  Now you can understand why can not exist two resource files with the same name. Two resource files with same name will create two global function always with the same name and this will be reported as an error by the linker. Since the static library will became part of the main executable file the macro can be called, as already said, from inside the main() body without any particular problem. On the contrary, in case of shared library, the same call will not work cause the global function created inside the shared library is not automatically marked as exported than the linked will not find it during compilation. Solutions to fix this problem can be many but the most simply way would be to export a shared library initialization function to call from main() code and, inside this function, use the resource initialization macro. Follow the example main code:

// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    Q_INIT_RESOURCE(mystaticlibrary);
    MySharedLibrary::InitResources();

    return a.exec();
}

// mysharedlibrary.cpp
void MySharedLibrary::InitResources()
{
    Q_INIT_RESOURCE(mysharedlibrary);
}

The example project show the two icons loaded by the static and shared libraries as follow. Once the initialization macro has been called the function can be loaded from every part of the code as standard main resources.


Comments

Post a Comment

Popular posts from this blog

Access GPIO from Linux user space

Android: adb push and read-only file system error

Tree in SQL database: The Nested Set Model