Вы когда-нибудь использовали Adobe Photoshop? Для мирян плагины - это просто кодовые блоки, предоставляемые приложению снаружи (например, в DLL). Разница между плагином и обычным DLL заключается в том, что плагин имеет возможность расширить функциональность родительского приложения. Например, сам Photoshop не имеет большого количества функций обработки изображений. Добавление плагинов дает ему потрясающий эффект, такой как размытие, точковое и все другие стили, и ни один из них не имеет самого родительского приложения.
Это очень хорошо для программ обработки изображений, но почему вам нужно тратить много усилий, чтобы выполнить коммерческие приложения, которые поддерживают плагины? Предположим, давайте приведем пример, что ваше приложение будет генерировать некоторые отчеты. Ваши клиенты обязательно будут просить обновления или добавлять новые отчеты. Вы можете использовать внешний генератор отчетов, такой как Report Smith, который является не очень похожим на решение, требует публикации дополнительных файлов, дополнительного обучения для пользователей и так далее. Вы также можете использовать QuickReport, но это поставит вас в кошмар управления версией - если вы хотите восстановить свое приложение каждый раз, когда вы меняете шрифт.
Однако, пока вы делаете отчет в плагин, вы можете использовать его. Нужен новый отчет? Нет проблем, просто установите DLL, и вы увидите его в следующий раз, когда начнется приложение. Другим примером является приложение, которое обрабатывает данные из внешних устройств (например, сканеры штрих -кода). Записав каждую подпрограмму обработки интерфейса устройства в качестве плагина, вы можете достичь максимальной масштабируемости, не внося никаких изменений в родительское приложение.
начиная
Самая важная вещь, прежде чем вы начнете писать код, - это выяснить, какие функции необходимо расширить ваше приложение. Это связано с тем, что плагин взаимодействует с родительским приложением через конкретный интерфейс, который будет определяться в соответствии с вашими потребностями. В этой статье мы создадим 3 плагина, чтобы продемонстрировать несколько способов взаимодействия плагина с родительским приложением.
Мы сделаем плагин в DLL. Перед этим, однако, мы должны сделать оболочку, чтобы загрузить и проверить их. На рисунке 1 показана тестовая программа после загрузки первого плагина. Первый плагин не выполняет ничего большого, и на самом деле все, что он делает, это возвращает строку, которая описывает себя. Тем не менее, это подтверждает важный момент-он будет работать должным образом с плагированными приложениями или без него. Если плагин нет, он не появится в списке установленных плагинов, но приложение все еще может выполнять функции нормально.
Единственная разница между нашим плагин-оболочкой и обычными приложениями-это блок Sharemem в исходном файле проекта, который появляется в пункте «Использование» и код, который загружает файл плагина. Любое приложение, которое передает параметры строки между собой и детьми DLL? Чтобы проверить эту оболочку, вам необходимо скопировать файл delphimm.dll из каталога Delphi/bin в путь, содержащийся в переменной среды пути или в каталоге, где находится приложение. Файл также должен быть распределен одновременно, когда выпускается окончательная версия.
Плагин загружается в эту испытательную оболочку через процесс LoadPlugins, который вызывается в событии FormCreate в главном окне, см. Рисунок 2. В этом процессе используются функции FindFirst и FindNext, чтобы найти файлы плагина в каталоге, где находится приложение. После поиска файла используйте процесс LoadPlugins, показанный на рисунке 3, чтобы загрузить его.
{Найти файлы плагинов в каталоге приложений}
Процедура tfrmmain.loadplugins;
вар
SR: TsearchRec;
Путь: строка;
Найдено: целое число;
Начинать
PATH: = ExtractFilePath (Application.Exename);
пытаться
Найдено: = findfirst (path + cplugin_mask, 0, sr);
пока найдено = 0, начинается
LoadPlugin (SR);
Найдено: = findnext (sr);
конец;
Окончательно
Findclose (SR);
конец;
конец;
{Загрузите указанный плагин DLL.
Процедура tfrmmain.loadplugin (sr: tsearchrec);
вар
Описание: строка;
Libhandle: целое число;
DescriptOproc: tplugindescribe;
Начинать
Libhandle: = LoadLibrary (pchar (Sr.name));
Если libhandle $#@60; $#@62;
Начинать
DescriptionEproc: = getProcAddress (libhandle, cplugin_describe);
Если назначено (descriptOproc), то
DescriptionProc (описание);
Memplugins.lines.Add (описание);
конец
еще
Начинать
Messagedlg ('file "' + sr.name + '" не является допустимым плагином.',
mtinformation, [mbok], 0);
конец;
конец
еще
MOSSAGEDLG («Произошла ошибка, загружая плагин" ' +
sr.name + '".', mterror, [mbok], 0);
конец;
Метод Loadplugin демонстрирует ядро механизма плагина. Во -первых, плагин написан как DLL. Во -вторых, он загружается динамически через API Loadlibrary. Как только DLL загружен, нам нужен способ получить доступ к процедурам и функциям, которые он содержит. Вызовы API GetProcadDress обеспечивают этот механизм, который возвращает указатель на необходимую подпрограмму. В нашей простой демонстрации плагин содержит только процедуру, называемую DescriptPlugin, указанную постоянной cplugin_describe (случай имени процедуры очень важен, и имя передаваемого для GetProcadRess должно быть точно таким же, как и имени, включенное в DLL) Полем Если в DLL нет запрошенной процедуры, GetProcadDree будет возвращать NIL, поэтому вы согласитесь использовать назначенную функцию для определения возвращаемого значения.
Чтобы хранить указатели на функцию простым в использовании, необходимо создать определенный тип для используемых переменных. Обратите внимание, что возвращаемое значение getProcAddress хранится в переменной, DescookProc, принадлежит типу tplugindescribe. Вот его утверждение:
тип
Tplugindescribe = процедура (var desc: string);
Поскольку процедура существует внутри DLL, она компилирует все процедуры экспорта посредством стандартных преобразования вызовов, поэтому требуется индикатор STDCALL. В этом процессе используется параметр var, который содержит описание плагина, когда процесс возвращает.
Чтобы позвонить в процесс, который вы только что получили, просто используйте переменную, которая сохраняет адрес в качестве имени процесса, за которым следует какие -либо параметры. В нашем случае утверждение:
DescriptionProc (описание)
Будет вызван процесс описания, полученный в подключателе, и переменная описания заполнена строкой, описывающей функциональность плагина.
Строительный плагин
Мы создали родительское приложение, и пришло время создать плагин, который мы хотим загрузить. Файл плагина является стандартным DLPHI DLL, поэтому мы создаем новый проект DLL от Delphi IDE и сохраняем его. Поскольку экспортируемая функция подключаемого модуля будет использовать параметры строки, блок Sharemen должен быть помещен первым в пункте использования проекта. На рисунке 4 приведен файл источника проекта нашего простого плагина.
Использование
Sharemem, Sysutils, классы,
основной в 'main.pas';
{$ E plg.}
экспорт
DescriptPlugin;
Начинать
конец.
Хотя плагин является файлом DLL, нет необходимости давать ему расширение .dll. На самом деле, одной из причин достаточно, чтобы дать нам повод изменить расширение: когда родительское приложение ищет загрузку файла, новое расширение может служить конкретной маской файла. Используя другое расширение (наш пример использует *.plg), вы можете быть в некоторой степени уверены, что приложение будет загружать только соответствующие файлы. Индикатор компиляции $ x может достичь этого изменения, или вы можете установить расширение через страницу приложения диалогового окна «Параметры проекта».
Код для первого примера плагина очень прост. На рисунке 5 показан код, содержащийся в новом блоке. Обратите внимание, что прототип DescriptionEplugin согласуется с типом Tplugindescribe в приложении Shell, и использует дополнительное зарезервированное слово для экспорта, чтобы указать, что процесс будет экспортирован. Экспортируемое имя процесса также появится в разделе экспорта основного исходного кода проекта (перечислен на рисунке 4).
единица главного;
интерфейс
процедура descriptOplugin (var desc: string);
экспорт;
Выполнение
процедура descriptOplugin (var desc: string);
Начинать
Desc: = 'Тестовый плагин v1.00';
конец;
конец.
Перед тестированием этого плагина скопируйте его на путь основного приложения. Самый простой способ состоит в том, чтобы создать плагин в подкаталоге домашнего каталога, а затем установить выходной путь к основному пути (каталоги/условия диалогового окна «Параметры проекта» также можно использовать для этого настройки).
отлаживать
Теперь позвольте мне представить лучшую функцию в Delphi 3: способность отладки DLL от IDE. В проекте DLL вы можете указать программу в качестве приложения хоста через диалоговое окно Run Paramate. Затем вы можете установить точки останова в коде DLL и нажать F9, чтобы запустить его - точно так же, как вы делаете в обычном приложении. Delphi запустит указанную хост -программу и, скомпилируя DLL с информацией отладки, направляет вас к точке останова в коде DLL.