QtResources/bg
[toc align_right="yes" depth="1"]
Написано от : Girish Ramakrishnan, ForwardBias Technologies
Общ преглед
Qt Resources предоставя платформено независим механизъм за вкарване на произволни бинарни данни, включително изображения и звуци, като част от изпълнимият файл на приложението. Вижте "документацията на ресурсите":http://doc.qt.nokia.com/snapshot/resources.html за по-подробна информация.
По отношение на имплементацията, ресурсите в Qt нямат нищо общо с "RES файловете":http://msdn.microsoft.com/en-us/library/ms648007.aspx на Windows или "resource forks":http://en.wikipedia.org/wiki/Resource_fork on Mac OS X.
Как работи
Ресурсните файлове (i.e .qrc files) са XML-и, които описват кои файлове трябва да се пакетират в крайният бинарен файл. Ресурсният компилатор rcc обхожда XML-а и генерира C/C++ код. Този генериран код съдържа C структура, която съдържа суровите данни на файловете, който се намират в .qrc. След това тези C-структури се събират в друга C-структура, за да формират дървовидна структура, така че файловете да могат да се наредят в йерархии. Детайлите за тази структура сами по себе си не са много интересни, за това и не са описани тук. С опцията compressed на rcc, данните в структурите се компресират със zlib (по подразбиране, компресирането е изключено).
C-структурите трябва да се регистрират в Qt, за да може то да знае за тях. Номера е, че в края на всеки генериран от rcc C++ файл, rcc слага извикване на qRegisterResourceData(), което регистрира C структурата в системата за ресурси на Qt. Чрез използването на подхода за конструктурна функция, qRegisterResourceData() се извиква преди main(). Подхода за конструктурната функция е използването на глобална статична променлива, която се инициализира като се извиква функция.
<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 />
В края на генерирания от rcc C++ файл, съдържа нещо подобно на:
<br />int qInitResources_images()<br />{<br /> qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data);<br /> return 1;<br />}
<br />Q_CONSTRUCTOR_FUNCTION(qInitResources_images)<br />
функциите и променливите в библиотеките, които не се използват/извикват от крайната програма се премахват от крайният бинарен код ( оптимизират се). Ако ресурсите са в споделена библиотека, тогава конструкторната функция се извиква. Обаче, повечето платформи зареждат споделените библиотеки при нужда и конструктурната функция се извиква само когато библиотеката се зарежда. Последствието от това е, че всички ресурси в плъгини, които се използват в главната програма, няма да бъдат намерени от Qt, докато плъгина не бъде зареден - това не е проблем, ако ресурсиоте от споделената библиотека се изпозлват само в нея. Обърнете внимание на това, че достъпването на ресурси от споделената библиотека в главното приложение не предизвиква зареждането и, тъй като никакви символи не се експортират от QRC системата.
Тъй като статичните променливи се инициализират преди извикаването на main(), всички ресурси автоматично се регистрират преди същинската програма да стартира.
h1. Q_INIT_RESOURCE
Трикът с конструкторната функция работи само ако генерирания C++ файл е компилиран и вързан за приложението директно. Ако ресурсите се използват в статична библиотека и тя е свързана с приложението, конструкторната функция никога няма да се извика. Това е в природата на C/C++ свръзването
Решението на този проблем е да се използва генерирана променлива( от AFUNC ## init_variable по-горе) или да се извика генерираната функция qInitResource_images(). Макросът Q_INIT_RESOURCE съществува с тази цел и се изисква, когато имате ресурси в статична или споделена библиотека.
<br />#define Q_INIT_RESOURCE_EXTERN(name) extern int qInitResources_ ## name();<br />
Макроса по-горе обикновено се слага в началото на main() за всеки qrc файл.
Достъпване на ресурси
QFile, QDir, QPixmap и т.н. могат да достъпват qrc файлове. Целият достъп до файлове в Qt минава през "QAbstractFileEngine":http://doc.trolltech.com/4.6/qabstractfileengine.html. QResource регистрира подклас на QAbstractFileSystemEngine при стартиране, който предоставя валидна система за достъп до файлове (през QAbstractFileEngine::create), когато името на файла започва с ":".
Именни пространства за ресурси
Когато използвате ресурси в плъгини, ресурсните пътища трябва да бъдат именовани. Използването на името на плъгина за именоване на ресурсното пространство е добра техника. За пример, :/plugin_name/resourcename. Ако съществуващ път до ресурси е регистриран втори път с различни данни, той се игнорира и се запазва първия.