使用libdl在C中的插件架构

时间:2010-05-21 14:09:30

标签: c plugins dynamic-library

我一直在玩弄,在C中编写一个小型IRC框架,我现在要扩展一些核心功能 - 但除此之外,我希望它可以通过插件进行扩展!

到目前为止,每当我写一些IRC相关的东西时(我写了很多东西,现在大约有6种不同的语言......我很着火!)并且实际上继续实现了一个插件架构,它是在一个内部解释性的语言,有设施(读取:滥用),就像在Ruby中干扰整个脚本文件eval一样(糟糕!)。

现在我想在C中滥用某些东西!

基本上我可以做三件事

  1. 在我的程序中定义一个简单的脚本语言
  2. 使用现有的,嵌入口译员
  3. 使用libdl在运行时加载* .so模块
  4. 我喜欢第三个,如果可能,请避开其他两个选项。也许我是某种形式的受虐狂,但我认为这对于学习目的来说既有趣又有用。

    逻辑思考,明显的“痛苦链”将是(从最低到最高)2 - > 1 - > 3,原因很简单,libdl正在处理原始代码,这些代码可能(并且将会)在我的脸上爆炸。

    所以这个问题告诉你,stackoverflow的其他用户,你认为libdl能胜任这个任务,还是一个现实的想法?

3 个答案:

答案 0 :(得分:3)

libdl非常适合插件架构 - 在某些范围内:-)。它在很多不同的软件中用于这种目的很多。它适用于主程序和插件之间有明确定义的API /接口的情况,并且许多不同的插件实现相同的API /接口。例如,您的IRC客户端可能具有实现不同IM协议(Jabber,MSN,Sametime等...)的网关的插件 - 所有这些都非常相似,因此您可以使用诸如“发送消息”之类的功能来定义API “,”检查回复“等 - 并编写一堆插件,每个插件都实现了不同的协议。

它运行得不好的情况是你希望让插件对主程序的行为进行任意改变 - 例如,Firefox插件可以改变浏览器选项卡的行为,它们的外观,添加/删除按钮等。这种事情在动态语言中更容易实现(因此,为什么很多Firefox都是用javascript实现的),如果这是你想要的那种自定义,你最好选择你的选项(2),并编写一个很多用脚本语言的UI ......

答案 1 :(得分: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解释器......也许你可以想出一些简单的基于正则表达式采取行动的东西。

尽管如此,插入模块不仅可以让您的生活变得更简单,而且还可以帮助您建立一个人们社区,围绕您制作的任何东西进行开发。

答案 2 :(得分:1)

有很多现有的C程序使用dlopen() / dlsym()来实现插件架构(包括多个与IRC相关的架构);所以是的,这绝对取决于任务。