Создание разделяемых библиотекВ следующих разделах перечислены определённые вещи, которые должны быть приняты во внимание при создании разделяемых библиотек. Использование символов из разделяемых библиотекСимволы - функции, переменные или классы - содержащиеся в разделяемых библиотеках и предназначенные для использования клиентами, такими как приложения или другие библиотеки, должны быть специальным способом помечены. Эти символы называются общедоступными символами, которые экспортируются или делаются публично видимыми. Остальные символы не должны быть видимы снаружи. На большинстве платформ компиляторы скрывают их по умолчанию. На некоторых платформах необходим специальный параметр компилятора для скрытия этих символов. При компиляции разделяемой библиотеки она должна быть помечена для экспорта. Чтобы использовать разделяемые библиотеки в клиенте, некоторые платформы могут также потребовать специального объявления импорта. В зависимости от вашей целевой платформы Qt предоставляет специальные макросы, которые содержат необходимые определения:
Теперь мы должны удостовериться, что вызывается правильный макрос -- когда мы компилируем саму разделяемую библиотеку или когда клиент просто использует разделяемую библиотеку. Обычно это может быть решено добавлением специального заголовочного файла. Допустим, мы хотим создать разделяемую библиотеку, называемую mysharedlib. Специальный заголовочный файл для этой библиотеки mysharedlib_global.h похож на это: #include <QtCore/QtGlobal> #if defined(MYSHAREDLIB_LIBRARY) # define MYSHAREDLIB_EXPORT Q_DECL_EXPORT #else # define MYSHAREDLIB_EXPORT Q_DECL_IMPORT #endif В файле .pro разделяемой библиотеки мы добавляем: DEFINES += MYSHAREDLIB_LIBRARY В каждом заголовочном файле библиотеки мы указываем следующее: #include "mysharedlib_global.h" MYSHAREDLIB_EXPORT void foo(); class MYSHAREDLIB_EXPORT MyClass... Это гарантирует, что и библиотекой, и клиентами используется правильный макрос. Мы также используем эту технику в исходных файлах Qt. Рассмотрение заголовочных файловКак правило, клиенты будут подключать только общедоступные заголовочные файлы разделяемых библиотек. Эти библиотеки могут быть установлены в другом месте при разворачивании. Поэтому важно исключить другие внутренние заголовочные файлы, которые были использованы при создании разделяемой библиотеки. Например, библиотека может предоставлять класс, который который является обёрткой для аппаратного устройства и содержит дескриптор этого устройства, предоставляемый некоторой сторонней библиотекой: #include <footronics/device.h> class MyDevice { private: FOOTRONICS_DEVICE_HANDLE handle; }; Подобная ситуация возникает с формами, создаваемыми Qt Designer, при использовании агрегирования или множественного наследования: #include "ui_widget.h" class MyWidget : public QWidget { private: Ui::MyWidget m_ui; }; При развёртывании библиотеки не должно быть никаких зависимостей с внутренними заголовочными файлами footronics/device.h или ui_widget.h. Этого можно избежать, используя идиому указателя на реализацию, описанную в различных книгах по программированию на C++. Для классов с семантикой значений рассмотрите возможность использования QSharedDataPointer. Бинарная совместимостьДля корректной работы клиентов, загружающих разделяемую библиотеку, расположение в памяти используемых классов должно точно соответствовать расположению в памяти версии библиотеки, которая была использована при компиляции клиента. Другими словами, библиотека, найденная клиентом во время выполнения, должна быть совместима на уровне двоичных кодов с версией, используемой во время компиляции. Обычно это не проблема, если клиент является автономным программным пакетом, который поставляется со всеми библиотеками, которые ему необходимы. Однако, если клиентское приложение полагается на разделяемые библиотеки, которые относятся к другому установочному пакету или операционной системе, то нам необходимо подумать о схеме управления версиями разделяемых библиотек и решить, на каком уровне будет поддерживаться бинарная совместимость. Например, библиотеки Qt с одним и тем же номером major-версии будут гарантированно совместимы на уровне двоичных кодов. Поддержка бинарной совместимости накладывает некоторые ограничения на изменения, которые вы можете делать в классах. Хорошее объяснение можно найти в KDE - Вопросы политики/бинарной совместимости в C++. Эти проблемы должны рассматриваться с самого начала разработки библиотеки. Мы рекомендуем, чтобы принцип сокрытия информации и техника указателя на реализацию использовались везде, где это возможно. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |