代码之家  ›  专栏  ›  技术社区  ›  LukeN

基于libdl的C插件体系结构

  •  6
  • LukeN  · 技术社区  · 16 年前

    到目前为止,每当我写一些与IRC相关的东西(我写了很多,现在用了6种不同的语言。。。我着火了!)实际上,它是在一种解释语言中实现的插件架构,这种解释语言有这样的功能(读:滥用),就像阻塞整个脚本文件一样 eval 在红宝石(坏!)。

    基本上我可以做三件事

    1. 在我的程序中定义一种简单的脚本语言
    2. 使用libdl在运行时加载*.so模块

    我喜欢第三种,如果可能的话,拉瑟尽量避免其他两种选择。也许我是某种受虐狂,但我认为这对学习既有趣又有用。

    从逻辑上看,明显的“痛苦链”应该是(从最低到最高)2->1->3.原因很简单,libdl处理的原始代码可能(而且将)经常在我面前爆炸。

    所以,stackoverflow的用户朋友们,这个问题摆在你们面前,你们认为libdl能胜任这个任务吗,甚至是一个现实的想法?

    3 回复  |  直到 16 年前
        1
  •  3
  •   psmears Touffy    16 年前

    libdl 非常适合于插件体系结构-在特定范围内:-)。它在很多不同的软件中被大量地用于这种目的。在主程序和插件之间有一个定义良好的API/接口,并且许多不同的插件实现相同的API/接口的情况下,它工作得很好。例如,您的IRC客户机可能有实现不同IM协议(Jabber、MSN、Sametime等)网关的插件—所有这些都非常相似,因此您可以使用“发送消息”、“检查回复”等函数定义API—并编写一组插件,每个插件实现不同的协议。

    它工作不太好的情况是,您希望插件对主程序的行为进行任意更改—例如,Firefox插件可以更改浏览器选项卡的行为、它们的外观、添加/删除按钮等等。在动态语言中实现这类功能要容易得多(因此大部分Firefox都是用javascript实现的),如果这是您想要的定制方式,那么您最好选择(2),并用脚本语言编写大量UI。。。

        2
  •  3
  •   Tim Post Samir J M Araujo    16 年前

    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翻译。。也许你能想出一些方法,让基于正则表达式的操作变得简单。

    不过,插件模块不仅能让你的生活更简单,还能帮助你建立一个社区,让人们围绕着你的产品开发东西。

        3
  •  1
  •   caf    16 年前

    dlopen() / dlsym() 实现插件架构(包括多个与IRC相关的架构);所以,是的,它肯定是由任务。

    推荐文章