2010-05-21 4 views
6

Я занимался рекламой небольшой структуры IRC в C, которую я сейчас собираюсь расширить с помощью некоторых основных функциональных возможностей, но помимо этого я бы хотел, чтобы она расширялась с помощью плагинов !Архитектура плагина в C с использованием libdl

До сих пор, всякий раз, когда я писал что-то, связанное с IRC (и я написал много, примерно на 6 разных языках сейчас ... Я в огне!) И на самом деле пошел дальше, чтобы внедрить архитектуру плагина, она была внутри интерпретируемый язык, в котором есть возможности для выполнения (чтение: злоупотребление), поэтому, как забивание всего файла сценария через eval в Ruby (плохо!).

Теперь я хочу оскорбить что-то в C!

В основном есть три вещи, которые я мог бы сделать

  1. определить простой язык сценариев внутри моей программы
  2. использовать существующий, вложение переводчика
  3. использовать libdl для загрузки * .so модули во время выполнения

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

Логическое мышление, очевидная «цепочка боли» будет (от низкого до высшего) 2 -> 1 -> 3, по той простой причине, что libdl имеет дело с необработанным кодом, который может (и будет) взорваться на моем лице чаще да, чем нет.

Так что этот вопрос выходит вам, другие пользователи stackoverflow, вы думаете, что libdl соответствует этой задаче или даже реалистичной мысли?

ответ

3

libdl очень хорошо подходит для подключаемых архитектур - в определенных границах :-). Он используется много для такой цели в множестве разных программ. Он хорошо работает в ситуациях, когда есть четко определенный API/интерфейс между основной программой и плагином, а ряд различных плагинов реализуют один и тот же API/интерфейс. Например, ваш IRC-клиент может иметь плагины, которые реализуют шлюзы для разных протоколов IM (Jabber, MSN, Sametime и т. Д.) - все они очень похожи, поэтому вы можете определить API с такими функциями, как «отправить сообщение» »,« проверить на ответ »и т. д. - и написать кучу подключаемых модулей, в которых каждый реализовал другой протокол.

В ситуации, когда она работает менее эффективно, вы хотите, чтобы плагины вносили произвольные изменения в поведение основной программы - таким образом, например, плагины Firefox могут изменять поведение браузера вкладки, их внешний вид, кнопки добавления/удаления и т. д. Такого рода вещи намного проще достичь на динамическом языке (следовательно, почему большая часть Firefox реализована в javascript), и если это та настройка, которую вы хотите, вам может быть лучше с вашим вариантом (2), и написать много вашего UI на языке сценариев ...

+0

Изменения в основной функции - это не-go - я бы просто реализовал такие функции, как «on_channel_message (...)» - по другой мысли .. могут ли библиотеки загружаться с функциями доступа libdl, определенными в основной программе? – LukeN

+0

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

1

Существует множество существующих программ C, которые используют dlopen()/dlsym() для реализации архитектуры плагина (включая более одного связанного с IRC); так что да, это определенно зависит от задачи.

3

dlopen()/dlsym(), вероятно, самый простой способ пойти.Некоторые глупые код псевдо:

int run_module(const char *path, char **args) 
{ 
    void *module; 
    void (*initfunc)(char **agrs); 
    int rc = 0; 

    module = dlopen(path, RTLD_NOW); 
    if (module == NULL) 
     err_out("Could not open module %s", path); 

    initfunc = dlsym(module, "module_init"); 
    if (initfunc == NULL) { 
     dlclose(module); 
     err_out("Could not find symbol init_func in %s", path); 
    } 

    rc = initfunc(args); 

    dlclose(module); 

    return rc; 
} 

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

Возможно, вам понадобится нечто большее по линиям load_module(), выше всего загружается SO, ищет точку входа и блокируется до тех пор, пока эта точка входа не выйдет.

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

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

Смежные вопросы