Как лучше всего добавить функцию плагинов в программу Delphi - PullRequest
14 голосов
/ 14 декабря 2008

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

Это позволило бы сообществу пользователей писать расширения для моей программы для доступа к внутренним данным и добавлять возможности, которые они могут найти полезными.

Я видел сообщение по адресу: Предложения по добавлению возможностей плагинов? , но его ответы не кажутся переносимыми в программу Delphi.

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

Известны ли вам какие-либо ресурсы, компоненты или статьи, которые бы предлагали, как лучше всего это сделать в Delphi, или у вас есть свои рекомендации?

Ответы [ 9 ]

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

Первый вопрос, который я хотел бы задать: нужны ли плагины для доступа к пользовательскому интерфейсу вашего хост-приложения или для добавления каких-либо собственных элементов пользовательского интерфейса? Или плагины будут ограничены запросом и / или передачей данных вашему хост-приложению?

Последнее намного проще и открывает две возможности. Другие уже упоминали библиотеки DLL, и это первый путь. Применяются определенные предостережения - обычно вы должны взаимодействовать с DLL, используя только те типы данных, которые используются в Windows API. Таким образом, вы можете быть уверены, что библиотеки плагинов будут понимать ваши типы данных, независимо от того, на каком языке / компиляторе они были созданы. (Так, например, используйте PChars, а не строки. Как правило, не передавайте классы Delphi, такие как TStream, для DLL. В некоторых случаях это работает, но в целом небезопасно, потому что, даже если DLL была скомпилирована в Delphi, возможно, это была другая версия компилятора с немного отличным представлением о том, что такое TStream). Google для использования DLL в Delphi, и вы найдете еще много советов.

Еще один способ, который еще не был упомянут, - включить скрипты в самом приложении. Существует несколько очень мощных сторонних скриптовых движков, как коммерческих, так и бесплатных, и большинство из них позволяют вам обмениваться объектами Delphi со скриптом. Некоторые из этих библиотек поддерживают только Pascal в качестве языка сценариев, другие позволят вам использовать Basic (возможно, лучше для начинающих пользователей) или другие языки. См., Например, сценарий RemObjects Pascal (бесплатно) по адресу http://www.remobjects.com/free.aspx.

На данный момент моим любимым скриптовым решением является Python для Delphi (P4D, также бесплатный) с http://mmm -experts.com / Products.aspx? ProductID = 3 . Он может прекрасно взаимодействовать с вашими классами посредством RTTI и позволяет выполнять код Python в вашем приложении Delphi, а также использовать классы Delphi в скриптах Python. Учитывая популярность Python, это может быть жизнеспособным решением, если вы хотите привлечь разработчиков к своему проекту. Однако для каждого пользователя должен быть установлен дистрибутив Python.

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

Теперь вернемся к моему первоначальному вопросу: все становится намного сложнее, если вам нужны плагины для взаимодействия с вашим пользовательским интерфейсом, например, поместив элементы управления на него. Как правило, библиотеки DLL не могут быть использованы для этого. Санкционированный Borland / CodeGear способ заключается в использовании пакетов (BPL). С BPL вы можете получить доступ и создать экземпляры классов, предлагаемых плагином, как если бы они были объявлены в вашем хост-приложении. Суть в том, что все BPL должны быть скомпилированы с одной и той же версией и сборкой Delphi, что и ваше основное приложение. По моему мнению, это делает пакеты совершенно непрактичными, поскольку трудно ожидать, что все потенциальные авторы плагинов по всему миру будут использовать ту же версию Delphi, что и вы. Большая ловушка.

Чтобы обойти это, я экспериментировал с другим подходом: продолжайте использовать библиотеки DLL и разрабатывайте синтаксис для плагина для описания нужного ему пользовательского интерфейса, а затем создайте его самостоятельно в хост-приложении. (XML является удобным способом выражения пользовательского интерфейса, поскольку вы получаете концепцию родительского / вложенного доступа бесплатно.) Синтаксис описания пользовательского интерфейса может включать в себя обратные вызовы библиотеки DLL, запускаемые при изменении содержимого или состояния элемента управления. Этот метод ограничит плагины набором элементов управления VCL, которые ваше приложение уже использует или зарегистрировало. И это не работа на одну ночь, в то время как BPL, безусловно, есть.

Гугл тоже для "Delphi plugin framework". Есть несколько готовых решений, но, насколько я знаю, они обычно используют BPL, с их ограниченной полезностью.

9 голосов
/ 14 декабря 2008

На самом деле, принятый ответ на вопрос, который вы цитируете , вполне подходит и для Delphi. Ваши плагины будут DLL, и вы можете диктовать, что они должны экспортировать функцию с определенным именем и подписью. Затем ваша программа загрузит DLL (с ​​LoadLibrary) и получит адрес функции (с GetProcAddress). Если DLL не загружается или ее нет, то DLL не является плагином для вашего приложения.

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

При тестировании вашей системы плагинов будет разумно написать плагин самостоятельно на языке, отличном от Delphi. Таким образом, вы можете быть более уверенными в том, что случайно не потребовали, чтобы все использовали Delphi.

7 голосов
/ 15 декабря 2008

Сначала я выбрал базовые плагины BPL и DLL. И нашел их трудно поддерживать.

Если вы используете систему BPL, то вам необходимо сопоставить версию BPL с версией EXE. Это включает в себя обновления Delphi, которые могут что-то сломать. Я обнаружил (трудный путь), что если мне нужно включать все мои плагины в каждый релиз, то нет смысла иметь плагины вообще.

Затем я переключился на простые плагины DLL. Но эта система просто сложная кодовая база. И это не очень хорошая вещь.

Разбивая сеть, я обнаружил Lua встроенный язык сценариев и поставил его вместе с ним. Lua - это DLL-библиотека размером 150 Кб, встраивающая компилятор байт-кода, интерпретатор и очень простой и умный язык динамического программирования.

Мои плагины - простые скрипты lua. Легко и вручную. Есть готовые примеры Delphi, поэтому вы можете экспортировать любой класс или процедуру в виде таблицы или функции Lua. GUI или нет. Например, у меня в приложении было приложение TurboPower Abbrevia для архивирования. Я экспортировал свой zip-класс в lua, и теперь все плагины могут вызывать zip ('. ', 'dir.zip') и unzip (). Затем я переключился на 7zip и реализовал только старый класс для использования 7zip. Все плагины работают так же, как и раньше, с поддержкой нового zip ('. ', 'dir.7z').

Я создал TLuaAction, который вызывает из своего скрипта процедуру Execute (), Update (), Hint ().

У Lua allso есть своя собственная система плагинов, которая позволяет легко добавить функциональность. Например, luacom make прост в использовании для автоматизации COM, luainterface позволяет вызывать .net из lua. См. luaforge для получения дополнительной информации. Существует Lua IDE, сделанная в Delphi, с исходным кодом.

6 голосов
/ 14 декабря 2008

Я пытался сделать обзор всех таких опций некоторое время назад. Вместе с моими читателями / комментаторами мы создали этот список:

  • DLL / BPL загружается из программы.
  • DLL / BPL, загруженные из песочницы (которая может быть другой копией программы или специализированного "серверного" приложения и которая взаимодействует с основной программой через сообщения / сокеты / msmq / именованные каналы / почтовые слоты / файлы отображения памяти).
  • COM (в любом из его вариантов).
  • DDE (пожалуйста, не надо).
  • Внешняя программа, которая взаимодействует через стандартный ввод / вывод.
  • Внешняя программа, которая взаимодействует через файлы (имя файла является параметром программы).
  • Внешняя программа, работающая через папку удаления (полезна для пакетной обработки).
  • Внешняя программа, которая взаимодействует с сообщениями Windows / сокетами Windows / msmq / именованными каналами / почтовыми ящиками / файлами отображения памяти / базой данных публикации-подписки.
4 голосов
/ 15 декабря 2008

Самый универсальный метод добавления возможностей плагина - это использование COM. Хорошая книга для начинающих в дороге - Delphi Com Programming от Эрика Хармона. Хотя он изначально был написан для версий Delphi с 3 по 5, содержание книг по-прежнему актуально для последних версий Delphi.

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

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

Я использую плагины для реализации большей части функциональности созданного игрового движка. Основной EXE-файл состоит из скриптового движка, менеджера плагинов, некоторых основных графических подпрограмм и многого другого. Я использую TJvPluginManager из библиотеки JEDI VCL. Это очень хороший менеджер, и он может добавить в вашу программу практически все, что вы захотите. Посмотрите демонстрации, включенные в пакет, чтобы увидеть, как он работает. Единственным недостатком является то, что он добавляет много кода JCL / JVCL в вашу программу, но на самом деле это не проблема, если вы уже используете другие компоненты JVCL.

2 голосов
/ 19 декабря 2008
2 голосов
/ 14 декабря 2008

Если плагины будут разрабатываться в Delphi или C ++ builder, используйте пакеты + интерфейсы. Delphi OTA является хорошим примером для этого. Если плагины не зависят от языка, COM - хороший способ.

Дополнение: Если вы не будете использовать COM, вам может потребоваться предоставить SDK для каждого языка. И обработка типов данных между различными языками может быть болезненной (например, тип строки delphi). Поддержка Delphi COM превосходна, вам не нужно беспокоиться о деталях. Это в основном не подходит для поддержки Delphi COM. Не пытайтесь изобретать колесо снова. Я удивлен, почему люди не склонны упоминать об этом.

1 голос
/ 14 декабря 2008

Вы можете взглянуть на Гидра от Remobjects. Это позволит вам не только добавлять плагины, но и смешивать win32 и .net.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...