Плагин API дизайн - PullRequest
       38

Плагин API дизайн

12 голосов
/ 09 декабря 2008

Итак, у меня есть приложение, которое в значительной степени основано на API QT, использующее систему QPlugin. Его довольно просто использовать, вы определяете класс, который наследуется от интерфейса, и когда плагин загружается, вы получаете экземпляр этого класса. В конце все сводится к dlopen / dlsym или LoadLibrary / GetProcAddress, в зависимости от того, что подходит для ОС. У меня нет проблем, здесь все работает, как ожидалось.

Итак, к вопросу. Существует много функциональных возможностей, включающих плагин, который должен ссылаться на данные / функции, предоставляемые основным приложением. Например, мое приложение имеет графический интерфейс, поэтому в моем приложении есть функция "plugin::v1::gui", которая возвращает QWidget *. Если я хочу, чтобы плагин мог добавлять элементы в мой пользовательский интерфейс или даже сделать его диалог дочерним по отношению к моему пользовательскому интерфейсу, ему понадобится указатель на него.

Я начал разработку для Linux и быстро столкнулся с тем, что по умолчанию загрузчик не заполняет неразрешенные символы в общих объектах символами из приложения, загружающего его. Нет проблем, легко исправить. добавьте "-rdynamic" к моим флагам и двигайтесь дальше. Все работает хорошо.

Теперь я обнаружил, что в Windows нет аналога :(. Так что же является хорошим решением?

Пока лучшее, что я придумал, - это структура, которую я заполняю в своем основном приложении, в которой есть указатели на каждый объект / функцию, о которых может заботиться плагин. Затем, передав это в функцию плагина "init()", и теперь он имеет правильные указатели на все, но это раздражающее решение, так как теперь мне приходится вносить изменения в нескольких местах, когда я что-то добавляю.

Есть ли лучшее решение? Как сообщество SO справилось с этим?

Ответы [ 3 ]

4 голосов
/ 10 декабря 2008

Создайте набор интерфейсов для основных объектов взаимодействия, которые будут отображаться вашим приложением, и создайте их в собственной библиотеке lib / dll и реализуйте эти интерфейсы в классах в своем приложении по мере необходимости. Библиотека должна также включать интерфейс плагина, возможно, просто с помощью метода «initialize», который будет реализован объектом плагина.

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

Популярный способ сделать это простым - реализовать иерархию, аналогичную DOM, в вашем приложении, чтобы плагин мог получить доступ ко всем соответствующим объектам в вашем приложении из одного корневого объекта.

0 голосов
/ 09 декабря 2008

Вы сделали это относительно хорошим способом. Вспомогательные классы часто являются чистым способом (только) ВСТАВКИ новых функций. Если вы заново разрабатываете свое программное обеспечение, вы должны отметить, что не каждый плагин должен получить доступ к вашей административной структуре. Так что должны быть различия в дизайне плагинов.

Одна возможность: Создайте некоторые абстрактные классы, от которых вы наследуете, которые идут с функциональностью, чтобы установить необходимые указатели на виджеты или около того.

Другая возможность: Расширьте свои основные (родительские) классы с помощью функций getParent (). GetMainWidget (), getParent (). GetConfigWidget () ....


Если речь идет только о динамической загрузке пользовательского интерфейса из вашего UI-плагина без использования указателей, вы можете сделать это, как описано на этой странице: http://dolzhenko.blogspot.com/2008/10/qt4-dynamic-loading-ui-from-other-ui_07.html

Это делается с помощью ui-файлов, к которым вы можете получить доступ через ваши основные конфигурационные файлы или как угодно.

0 голосов
/ 09 декабря 2008

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

Существуют и более тяжелые решения, такие как CORBA ...

...