Подтвердить что ты не робот

Внедрение плагиновой системы в C или С++

Каковы ваши советы по внедрению системы стиля плагина?

4b9b3361

Ответ 1

В C (и я думаю, что С++ тоже, хотя я сам этого не делал), это чаще всего выполняется с использованием динамически загружаемых модулей. API: s для таких приложений зависит от платформы.

В POSIX (Linux) вы используете семейство функций dlopen(). В основном вы создаете свой плагин отдельно, затем загружаете его во время выполнения, просматриваете его символы по имени и затем можете вызвать их.

Для Win32 существует LoadLibrary(), который делает что-то очень похожее, вы создаете свой код в DLL.

Для удобной обертки, которая делает все это простой и прозрачной, ознакомьтесь с GLib API GModule.

Ответ 2

В временном интервале '92/'93 я работал над архитектурой плагина для Aldus PageMaker, которая была закодирована на С++. PageMaker был построен на основе С++ OOP под названием VAMP, который помогал его переносимости между Mac OS и Windows.

Итак, мы попытались использовать возможности С++ для создания архитектуры плагина. Это оказалось очень проблематичным для классов С++ из-за так называемой проблемы хрупкого базового класса. Я приступил к написанию статьи, которая была опубликована в журналах, и что я представил в OOPSLA '93 на семинаре по размышлениям. Я также связался с Бьярне Страуструпом на конференции Usenix в Портленде и несколько месяцев начал диалог с ним, где он отстаивал вопрос о решении проблемы хрупкого базового класса от моего имени. (Увы, другие вопросы считались более важными в то время.)

Microsoft представила систему COM/DCOM и для этой платформы, которая рассматривалась как жизнеспособное решение проблемы. С++ можно использовать в качестве языка реализации для COM через абстрактные классы, используемые для определения COM-интерфейсов.

Однако в наши дни разработчики избегают использования COM/DCOM.

Напротив, NeXT разработала архитектуру плагина с использованием Objective C в начале 90-х годов в рамках NeXT Step. Сегодня он живет в Mac OS X на компьютерах Apple и важных платформах, таких как iPhone.

Я предоставляю Objective C, позволяя решить проблему с плагином превосходным образом.

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

Если бы вы строили архитектуру плагина с семейством языков C, сделайте это с помощью Objective C.

Ответ 3

Лучший нейтральный совет платформы и языка, который я могу дать, таков:

Создайте все приложение вокруг SDK плагина.

IMO, плагин SDK не должен быть запоздалой. Если вы создаете свое приложение в основном как пустую оболочку, которая загружает плагины, то основные функции реализованы в вашем собственном SDK, вы получаете следующие преимущества:

  • Высокая модульность компонентов и четкое разделение цели (это своего рода сила вашей архитектуры).
  • Это заставляет ваш SDK быть действительно хорошим.
  • Он позволяет другим сторонним разработчикам создавать чрезвычайно мощные функции на уровне ядра, а также
  • Новые разработчики/наниматели могут легко начать работу над важной новой функцией без необходимости касаться основного приложения - они могут выполнять всю свою работу в плагине (что не позволяет им прикручивать что-либо еще)

В C/С++ вы, вероятно, используете динамические библиотеки ссылок и указатели на функции (C) или интерфейсы (классы, состоящие исключительно из чистых виртуальных методов, для С++). Однако, даже если вы используете Javascript, я бы порекомендовал вышеупомянутую архитектуру.

Ответ 4

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

Это, конечно, означало бы, что ваши плагины должны быть написаны в Lua. Если вам не нравится Lua, тогда де-факто стандартные интерпретаторы Perl, Python и Ruby записываются на C и могут быть встроены в программу C. Я знаю о ряде программ, которые используют эти языки в качестве расширений языка сценариев.

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

Ответ 5

Qt предоставляет QPluginLoader: http://qt-project.org/doc/qt-4.8/qpluginloader.html

Если вам нужен/нужен более мелкозернистый элемент управления, Qt также предоставляет средства для загрузки библиотек "на лету" с помощью QLibrary: http://qt-project.org/doc/qt-4.8/qlibrary.html

Даже лучше, они переносятся на разных платформах.

Ответ 6

Лучше всего использовать фреймворк, такой как ACE (http://www.cs.wustl.edu/~schmidt/ACE.html), который защищает вас (насколько это возможно) от специфичного для платформы кодирования.

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

Для абстракции более высокого уровня проверьте CIAO (http://www.cs.wustl.edu/~schmidt/CIAO.html) реализацию компонента CORBA с открытым исходным кодом на С++.

Ответ 7

Посмотрите Poco Class Loader, это может быть интересно для вас.

Ответ 8

Я написал статью о том, как реализовать систему плагинов с использованием динамических библиотек ссылок. Статья написана с точки зрения программиста Windows, но этот метод может быть применен к среде типа Linux/Unix.

Статья находится здесь: http://3dgep.com/?p=1759

Главное, вы должны создать "общую" DLL, которая неявно связана как основным приложением (основным приложением), так и реализациями плагина. Затем плагины могут быть явно связаны и загружены динамически во время выполнения основным приложением.

В статье также показано, как можно безопасно обмениваться статическим (singleton) экземпляром класса в нескольких DLL, используя "общую" DLL.

В статье также показано, как вы можете экспортировать функцию "C" или переменные из библиотеки DLL и использовать экспортированные функции в приложении во время выполнения.

Ответ 10

У меня был некоторый успех с использованием довольно наивной системы:

  • Создать спецификацию API для подключаемых модулей.
  • Использование диспетчера подключаемых модулей singleton
  • Использовать динамическую компоновку времени загрузки LoadLibrary/GetProcAddress
  • Реализация Инверсия обработки событий на основе управления для уведомления плагинов

Ответ 11

Я написал плагиновую библиотеку Pugg, которая загружает классы С++ из DLL файлов, и вот логика, которую я использовал

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

Функция

C регистрирует один или несколько классов factory под названием "Драйвер". Каждый класс драйвера связан со строкой. Когда основное приложение хочет создать класс, он собирает связанный класс factory, используя связанную строку. Я также внедрил систему проверки версий, чтобы не загружать старые плагины.

Загрузка Dll выполняется с использованием функций LoadLibraryA и GetProcAddress (теперь Pugg работает в окнах).

Следует упомянуть, что основное приложение и библиотеки dll должны быть скомпилированы с использованием одного и того же компилятора и с использованием тех же параметров компиляции (режимы выпуска/отладки, настройки оптимизации, stl-версии и т.д.). В противном случае могут возникнуть проблемы с отображением классов.