6

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

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

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

基本上我可以做三件事

  1. 在我的程序中定义一个简单的脚本语言
  2. 使用现有的,嵌入解释器
  3. 使用 libdl 在运行时加载 *.so 模块

我喜欢第三个,如果可能的话,我宁愿避免其他两个选项。也许我是某种受虐狂,但我认为这对学习目的既有趣又有用。

从逻辑上思考,明显的“痛苦链”将是(从最低到最高)2 -> 1 -> 3,原因很简单,libdl 正在处理可以(并且将会)更频繁地在我面前爆炸的原始代码.

所以这个问题问你,stackoverflow 的同胞们,你认为 libdl 能胜任这项任务,甚至是一个现实的想法吗?

4

3 回答 3

3

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

它工作得不太好的情况是您希望插件对主程序的行为进行任意更改 - 例如,Firefox 插件可以更改浏览器选项卡的行为,它们的外观、添加/删除按钮等。这种事情在动态语言中更容易实现(因此为什么大部分 Firefox 是用 javascript 实现的),如果这是你想要的那种定制,你可能会更好地使用你的选项 (2),并编写一个你的很多用户界面都是用脚本语言写的……

于 2010-05-21T14:19:46.277 回答
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 解释器……也许你可以想出一些东西,使基于正则表达式的操作变得简单。

尽管如此,插件模块不仅会让你的生活更简单,它们还会帮助你发展一个社区,让人们围绕你所做的任何事情开发东西。

于 2010-05-21T14:38:42.817 回答
1

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

于 2010-05-21T14:13:59.397 回答