QtResources: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
'''English''' [[QtResources SimplifiedChinese|简体中文]] [[QtResources_Bulgarian|Български]]<br />[[Category:QtInternals]]
'''English''' [[QtResources SimplifiedChinese|简体中文]] [[QtResources_Bulgarian|Български]]
[[Category:QtInternals]]


[toc align_right=&quot;yes&amp;quot; depth=&quot;1&amp;quot;]
[toc align_right="yes" depth="1"]


Written By : Girish Ramakrishnan, ForwardBias Technologies
Written By : Girish Ramakrishnan, ForwardBias Technologies
Line 7: Line 8:
= Overview =
= Overview =


Qt Resources provide a platform-independent mechanism for embedding arbitrary binary data, including images and sounds, as part of an application executable. See &quot;Documentation&amp;quot;:http://doc.qt.nokia.com/snapshot/resources.html for more details.
Qt Resources provide a platform-independent mechanism for embedding arbitrary binary data, including images and sounds, as part of an application executable. See "Documentation":http://doc.qt.nokia.com/snapshot/resources.html for more details.


Implementation-wise, Qt resources have nothing to do with &quot;RES files&amp;quot;:http://msdn.microsoft.com/en-us/library/ms648007.aspx on Windows or &quot;resource forks&amp;quot;:http://en.wikipedia.org/wiki/Resource_fork on Mac OS X.
Implementation-wise, Qt resources have nothing to do with "RES files":http://msdn.microsoft.com/en-us/library/ms648007.aspx on Windows or "resource forks":http://en.wikipedia.org/wiki/Resource_fork on Mac OS X.


= How it works =
= How it works =


Resource files (i.e .qrc files) are XML files that specify the files that should be packaged into the final binary. The ''rcc'' resource compiler parses the XML and generates C/C++ code. This generated code contains a C struct that contains the raw bytes of the files listed in the .qrc. These C-structs are then collated in another C-struct to form a tree-like structure as files can be arranged in hierarchies. The details of the C-struct itself is not very interesting, so it's not discussed here. With the <s>''compressed'' option to rcc, the data in the structs are compressed using zlib (by default, compression is off).
Resource files (i.e .qrc files) are XML files that specify the files that should be packaged into the final binary. The ''rcc'' resource compiler parses the XML and generates C/C++ code. This generated code contains a C struct that contains the raw bytes of the files listed in the .qrc. These C-structs are then collated in another C-struct to form a tree-like structure as files can be arranged in hierarchies. The details of the C-struct itself is not very interesting, so it's not discussed here. With the -''compressed'' option to rcc, the data in the structs are compressed using zlib (by default, compression is off).
<br />The C-structs need to be registered with Qt for Qt to know about them. The trick is that at the end of every rcc-generated C++ file, rcc places a call to qRegisterResourceData() which registers the C struct with the Qt resource system. By using the ''constructor function pattern'', the qRegisterResourceData() gets invoked before main(). The ''constructor function pattern'' is the usage of a global static variable that initializes itself by calling a function.<br /><code><br />#ifndef Q_CONSTRUCTOR_FUNCTION<br /># define Q_CONSTRUCTOR_FUNCTION0(AFUNC)  static const int AFUNC ## ''init_variable'' = AFUNC ();
 
# define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)<br />#endif<br /></code>
The C-structs need to be registered with Qt for Qt to know about them. The trick is that at the end of every rcc-generated C++ file, rcc places a call to qRegisterResourceData() which registers the C struct with the Qt resource system. By using the ''constructor function pattern'', the qRegisterResourceData() gets invoked before main(). The ''constructor function pattern'' is the usage of a global static variable that initializes itself by calling a function.
<br />The tail end of a rcc generated C++ file contains something like:<br /><code><br />int qInitResources_images()<br />{<br /> qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data);<br /> return 1;<br />}
<code>
<br />Q_CONSTRUCTOR_FUNCTION(qInitResources_images)<br /></code>
#ifndef Q_CONSTRUCTOR_FUNCTION
<br />Since static variables are initialized before main() is called, all resources are automatically registered before the actual program starts.
# define Q_CONSTRUCTOR_FUNCTION0(AFUNC)  static const int AFUNC ## ''init_variable'' = AFUNC ();
<br />h1. Q_INIT_RESOURCE
# define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
<br />The constructor function trick works only if the generated C++ file is compiled and linked to the main application directly. If the resources are used in a static library and the library is then linked to the main application, the constructor function will never get called. This is the by nature of C/C++ linking</s> functions and variables in libraries that are unused/uncalled from the final program are removed from the final binary (optimized out). If the resources are in a shared library, then the constructor function does get invoked. However, most platforms load shared libraries on demand and the constructor function gets called only when the shared library gets loaded. The consequence is that any resources in plugins used by the main program will not be found by Qt until the plugin itself gets loaded - it's not a problem if the resources in the shared library are used only in the shared library. Note that accessing the resource inside a shared object in the main application does not trigger loading of the shared object since no symbol is exported by QRC system to trigger loading of the shared object.
#endif
</code>
 
The tail end of a rcc generated C++ file contains something like:
<code>
int qInitResources_images()
{
qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
return 1;
}
 
Q_CONSTRUCTOR_FUNCTION(qInitResources_images)
</code>
 
Since static variables are initialized before main() is called, all resources are automatically registered before the actual program starts.
 
h1. Q_INIT_RESOURCE
 
The constructor function trick works only if the generated C++ file is compiled and linked to the main application directly. If the resources are used in a static library and the library is then linked to the main application, the constructor function will never get called. This is the by nature of C/C++ linking- functions and variables in libraries that are unused/uncalled from the final program are removed from the final binary (optimized out). If the resources are in a shared library, then the constructor function does get invoked. However, most platforms load shared libraries on demand and the constructor function gets called only when the shared library gets loaded. The consequence is that any resources in plugins used by the main program will not be found by Qt until the plugin itself gets loaded - it's not a problem if the resources in the shared library are used only in the shared library. Note that accessing the resource inside a shared object in the main application does not trigger loading of the shared object since no symbol is exported by QRC system to trigger loading of the shared object.


A solution to the above problems is to use the Q_INIT_RESOURCE macro, placed at the beginning of main(), which ensures that the resources are linked into the application in the case of static linking, or forces the loading of the library in the case of dynamic linking.
A solution to the above problems is to use the Q_INIT_RESOURCE macro, placed at the beginning of main(), which ensures that the resources are linked into the application in the case of static linking, or forces the loading of the library in the case of dynamic linking.
Line 26: Line 45:
= Accessing resources =
= Accessing resources =


QFile, QDir, QPixmap etc can all access qrc files. All file access in Qt goes through &quot;QAbstractFileEngine&amp;quot;:http://doc.trolltech.com/4.6/qabstractfileengine.html. QResource registers a QAbstractFileSystemEngine derivative on startup that provides a valid file system engine (through QAbstractFileEngine::create) when a file name has the &quot;:&quot; prefix.
QFile, QDir, QPixmap etc can all access qrc files. All file access in Qt goes through "QAbstractFileEngine":http://doc.trolltech.com/4.6/qabstractfileengine.html. QResource registers a QAbstractFileSystemEngine derivative on startup that provides a valid file system engine (through QAbstractFileEngine::create) when a file name has the ":" prefix.


= Namespacing resources =
= Namespacing resources =

Revision as of 08:58, 25 February 2015

English 简体中文 Български

[toc align_right="yes" depth="1"]

Written By : Girish Ramakrishnan, ForwardBias Technologies

Overview

Qt Resources provide a platform-independent mechanism for embedding arbitrary binary data, including images and sounds, as part of an application executable. See "Documentation":http://doc.qt.nokia.com/snapshot/resources.html for more details.

Implementation-wise, Qt resources have nothing to do with "RES files":http://msdn.microsoft.com/en-us/library/ms648007.aspx on Windows or "resource forks":http://en.wikipedia.org/wiki/Resource_fork on Mac OS X.

How it works

Resource files (i.e .qrc files) are XML files that specify the files that should be packaged into the final binary. The rcc resource compiler parses the XML and generates C/C++ code. This generated code contains a C struct that contains the raw bytes of the files listed in the .qrc. These C-structs are then collated in another C-struct to form a tree-like structure as files can be arranged in hierarchies. The details of the C-struct itself is not very interesting, so it's not discussed here. With the -compressed option to rcc, the data in the structs are compressed using zlib (by default, compression is off).

The C-structs need to be registered with Qt for Qt to know about them. The trick is that at the end of every rcc-generated C++ file, rcc places a call to qRegisterResourceData() which registers the C struct with the Qt resource system. By using the constructor function pattern, the qRegisterResourceData() gets invoked before main(). The constructor function pattern is the usage of a global static variable that initializes itself by calling a function.

#ifndef Q_CONSTRUCTOR_FUNCTION
# define Q_CONSTRUCTOR_FUNCTION0(AFUNC)  static const int AFUNC ## ''init_variable'' = AFUNC ();
# define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
#endif

The tail end of a rcc generated C++ file contains something like:

int qInitResources_images()
{
 qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
 return 1;
}

Q_CONSTRUCTOR_FUNCTION(qInitResources_images)

Since static variables are initialized before main() is called, all resources are automatically registered before the actual program starts.

h1. Q_INIT_RESOURCE

The constructor function trick works only if the generated C++ file is compiled and linked to the main application directly. If the resources are used in a static library and the library is then linked to the main application, the constructor function will never get called. This is the by nature of C/C++ linking- functions and variables in libraries that are unused/uncalled from the final program are removed from the final binary (optimized out). If the resources are in a shared library, then the constructor function does get invoked. However, most platforms load shared libraries on demand and the constructor function gets called only when the shared library gets loaded. The consequence is that any resources in plugins used by the main program will not be found by Qt until the plugin itself gets loaded - it's not a problem if the resources in the shared library are used only in the shared library. Note that accessing the resource inside a shared object in the main application does not trigger loading of the shared object since no symbol is exported by QRC system to trigger loading of the shared object.

A solution to the above problems is to use the Q_INIT_RESOURCE macro, placed at the beginning of main(), which ensures that the resources are linked into the application in the case of static linking, or forces the loading of the library in the case of dynamic linking.

Accessing resources

QFile, QDir, QPixmap etc can all access qrc files. All file access in Qt goes through "QAbstractFileEngine":http://doc.trolltech.com/4.6/qabstractfileengine.html. QResource registers a QAbstractFileSystemEngine derivative on startup that provides a valid file system engine (through QAbstractFileEngine::create) when a file name has the ":" prefix.

Namespacing resources