Как лучше всего добавить возможности плагинов в программу Delphi

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

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

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

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

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

14.12.2008 00:02:26
Смотрите дополнительное объяснение в моем ответе
Serguzest 14.12.2008 21:22:25
9 ОТВЕТОВ
РЕШЕНИЕ

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

Последнее намного проще и открывает две возможности. Другие уже упоминали библиотеки 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, безусловно, есть.

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

10
14.12.2008 15:01:50
+1. Здесь очень много полезных советов. Создание интерфейса плагина имеет много последствий в течение очень долгого времени, поэтому, чем больше вы думаете об этом заранее, тем лучше.
mghie 14.12.2008 15:21:52

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

1
14.12.2008 00:19:35

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

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

2
14.12.2008 21:20:16
Я не знаю, что такое Delphi OTA, и первоначальный поиск в Google не помог. У вас есть хорошая ссылка на ресурс, описывающий это?
lkessler 14.12.2008 00:37:17
Delphi OTA: API открытых инструментов. Первое попадание в Google: delphi.about.com/od/objectpascalide/a/wizardsexperts.htm
Rob Kennedy 14.12.2008 00:53:30
OTA = открытые инструменты api. Он предоставляет множество интерфейсов для использования функций IDE в пакетах expert или desingtime. Например, GExpert использует множество функций OTA. OTA не является родовой системой плагинов для программистов на Delphi. Это особенно относится к Delphi IDE. Я думал, что это может быть хорошим примером для вас.
Serguzest 14.12.2008 00:54:40
Неудачный URL: wizard-sex-perts.htm
lkessler 14.12.2008 03:02:23

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

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

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

9
14.12.2008 00:52:02
+1, намек на то, что плагины должны быть доступны для записи на других языках, кроме Delphi. В противном случае гораздо проще просто включить сценарии RemObjects Pascal в свое приложение и покончить с этим. Создание интерфейса к вашим внутренним объектам необходимо в обоих случаях ...
mghie 14.12.2008 14:53:32
и с помощью внутреннего скриптинга вам не нужно больше тратить силы на сам интерфейс плагина. Кроме того, убедитесь, что плагины можно тестировать, добавлять и удалять, не закрывая приложение.
mghie 14.12.2008 14:54:52
«Вы можете передать функцию через интерфейс ...» Как вы думаете, другие языки могут использовать или реализовывать интерфейсы delphi без COM?
Serguzest 14.12.2008 18:36:03
Mghie: PascalScript великолепен, но он не заменит настоящую систему плагинов, потому что он реализует только около 2/3 набора языковых функций, и всякий раз, когда кто-то спрашивает Карло Кока об оставшихся функциях, он почти всегда говорит, что не планирует внедрять их.
Mason Wheeler 14.12.2008 20:48:14
Интерфейс Ahmet, Delphi являются COM интерфейсы. Тем не менее, язык не нуждается в особой поддержке. Обычный старый C может сделать это просто отлично.
Rob Kennedy 15.12.2008 02:49:39

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

4
14.12.2008 02:14:25
TJvPluginManager ограничивает плагины написанными на Delphi? Как все-таки реализован интерфейс через COM?
mghie 14.12.2008 14:57:47
Да, плагины должны быть написаны на Delphi. (Или, может быть, C ++ Builder. Не уверен.) Плагины должны происходить от базового класса TJvPlugin, который по сути является просто оболочкой для функциональности вашего плагина, чтобы позволить ему общаться с менеджером. И вы можете реализовать его как DLL или BPL.
Mason Wheeler 14.12.2008 20:46:03

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

  • DLL / BPL загружается из программы.
  • DLL / BPL загружается из песочницы (которая может быть другой копией программы или специализированного «серверного» приложения и которая связывается с основной программой через сообщения / сокеты / msmq / именованные каналы / почтовые слоты / файлы отображения памяти).
  • COM (в любом из его вариантов).
  • DDE (пожалуйста, нет).
  • Внешняя программа, которая общается через стандартный ввод / вывод.
  • Внешняя программа, которая общается через файлы (имя файла является параметром программы).
  • Внешняя программа, работающая через дроп-папку (полезна для пакетной обработки).
  • Внешняя программа, которая взаимодействует с сообщениями Windows / сокетами Windows / msmq / именованными каналами / почтовыми ящиками / файлами отображения памяти / базой данных публикации-подписки.
6
14.12.2008 10:35:30

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

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

4
15.12.2008 03:58:29

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

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

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

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

Мои плагины - простые скрипты 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, с исходным кодом.

7
15.12.2008 10:12:38

Я нашел статью Тима Салливана: «
Внедрение плагинов для ваших приложений Delphi»

2
19.12.2008 01:51:50