Расширения это совместно используемая динамическая библиотека предназначенная для загрузки в процессе исполнения основного приложения, которая обязательно должна реализовывать хотя бы один специальный интерфейс.

Расширения делятся на два типа:

 Связь с расширением осуществляется с помощью интерфейса (сигналы, слоты и методы класса). Расширение загружается приложением при помощи класса QPluginLoader. Для загрузки расширения используется метод instance(), который создаёт объект расширения и возвращает указатель на него. Для выгрузки расширения используется метод unload().

  Первым этапом создадим класс интерфейсов наследуемый от QObject, в качестве интерфейса будет метод который принимает переменную типа QString и возвращает эту же строку в верхнем регистре. С помощью макроса Q_DECLARE_INTERFACE, задаём идентификотор интерфейсов, компилятор с генерирует метаинформацию для строки-идентификатор. Данный модуль является протоколом общения между плагином и основной программой и будет использоваться в проекте плагина и в основном проекте. 

Класс будет выглядеть следующем образом.

 Создадим базовое приложение которое будет загружать расширение. По нажатию кнопку будет происходить поиск расширения и загрузка его в систему. Далее через интерфейс будем задействовать нашу функцию.

Базовое приложение:

mainproject.h

 Создание расширения, первое что нужно сделать это в pro файле изменить типа собираемого проекта, для этого нужно добавить следующую строку TEMPLATE = lib, и задать конфигурацию проекта под расширения CONFIG += plugin.

upperstringplugin.pro

 Далее создаём класс будущего расширения, класс должен быть унаследован от класса интерфейсов. Макрос Q_INTERFACES, нужен что бы компилятор с генерировал всю необходимую мета информацию для расширения. Макрос Q_PLUGIN_METADATA(), задаёт точку входа в расширение и доступ для библиотеки Qt. Также нужно создать файл inteface.json с метаинформацией(файл должен находиться в корне проекта), в нашем случае там нет информации поэтому просто запишем пустые кавычки {} в файл.

upperstringplugin.h

 На выходе компиляции проекта мы получим файл с расширением .so, данный файл перемещаем в папку «Plugins» главного проекта и запускаем его. В данном случае расширение загружается в основную программу и создаётся единственный объект расширения. При попытки заново использовать функцию instance(), функция вернёт указатель на уже созданный объект расширения.

Выполнение программы



  Усложним нашу задачу, теперь нам нужно что бы расширение представляло собой виджет и что бы была возможность создавать несколько таких виджетов. Основная программа будет принимать сообщения от плагинов и отправлять обратно ответ. Создадим новые проекты, на первом этапе нам понадобиться два класса интерфейсов, один будет отвечать за загрузку расширения и создания виджета, другой за работу самого виджета.

Схема проекта будет выглядеть следующим образом:



 Первый класс interface будет иметь две функции, получить названия плагина и получить виджет плагина. Название плагина будем хранить для индентификации его в системе. Виджет плагина мы будем добавлять в MDI окна основного приложения.

 Второй класс является самим графическим виджетом, он унаследован от QWidget, здесь мы прописали необходимые нам функции, виджет будет получать сообщение и отправлять в основную программу.

interface.h

 Основная программа состоит из MDI окна, в котором есть основной виджет для принятия сообщений от плагинов и дополнительные окна, которые динамически появляются по мере вызова плагинов. 

При создания виджета плагина мы соединяем сигнал от плагина со слотом и с помощью функции sender() мы получаем указатель на плагин который прислал сообщение. Созданный виджет мы помещаем в MDI окно, а сам объект плагина можно выгрузить из системы.

mainproject.h

 Создаём плагин, его идея состоит в том что он является фабрикой для создания виджета.

plugin.h

 Инженер-программист