【转】C语言插件机制(下)
来源:互联网 发布:windows dns缓存时间 编辑:程序博客网 时间:2024/05/21 21:43
本文转自:http://abruzzi.iteye.com/blog/747159
前言
上一篇文章简单介绍了*NIX下的动态库的使用,我们在这篇文章中实现一个计算器,计算器程序calc本身不做运算,只是将操作数传递给具体的插件(adder, suber, muler, diver)来完成实际运算。首先,计算器根据插件配置文件plugin.xml来确定插件的位置,名称,入口符号的定义,然后依次调用各个插件完成计算。
插件列表
文中涉及到的插件定义在plugin.xml中,文档结构如下:
- <plugins>
- <plugin name="adder">
- <library path="/home/juntao/.libs/adder.so">
- </library>
- <entry name="add">
- </entry>
- </plugin>
- <plugin name="suber">
- <library path="/home/juntao/.libs/suber.so">
- </library>
- <entry name="sub">
- </entry>
- </plugin>
- <plugin name="muler">
- <library path="/home/juntao/.libs/muler.so">
- </library>
- <entry name="mul">
- </entry>
- </plugin>
- <plugin name="diver">
- <library path="/home/juntao/.libs/diver.so">
- </library>
- <entry name="div">
- </entry>
- </plugin>
- </plugins>
每个插件为一个plugin标签,plugin标签中包含library, entry两个字标签,分别定义动态库文件的路径及名称和插件函数的入口。为了简便,我们不重复设计list及xml解析,这里使用libxml2作为xml的分析器,GLIB中的GSList(单链表)来作为插件列表的链表对象。
每一个插件在C语言中的定义如下,非常简单(plugin.h)
- #ifndef _PLUGIN_H_
- #define _PLUGIN_H_
- typedef struct{
- char name[64];
- char path[256];
- char entry[128];
- int version;
- }Plugin;
- #endif
这里为了行文方便,Plugin结构中的字符串为静态尺寸。
计算器
计算器调用parseconf模块中的load_plugins将plugin.xml中定义的Plugin加载进一个GSList,以备后用:
- #include "plugin.h"
- extern int load_plugins(char *config, GSList **list);
插件中的函数原型应该符合接口定义:
- //pointer to function, which return a double, and get 2 double as input
- double (*pfunc)(double a, double b);
计算器的主要代码如下:
- int calc_test(double a, double b){
- GSList *list = NULL, *it = NULL;
- Plugin *pl = NULL;
- //insert a null node into list at first
- list = g_slist_append(list, NULL);
- int code = 0;
- double result;
- //load plugin defined in plugin.xml into list
- load_plugins("plugin.xml", &list);
- for(it = list; it != NULL; it = it->next){
- pl = (Plugin *)it->data;
- if(pl == NULL){
- continue;
- }else{
- //open the library
- flib = dlopen(pl->path, RTLD_LAZY);
- dlError = dlerror();
- if(dlError){
- fprintf(stderr, "open %s failed/n", pl->name);
- g_slist_free(list);
- return -1;
- }
- //get the entry
- *(void **)(&pfunc) = dlsym(flib, pl->entry);
- dlError = dlerror();
- if(dlError){
- fprintf(stderr, "find symbol %s failed/n", pl->entry);
- g_slist_free(list);
- return -1;
- }
- //call the function
- result = (*pfunc)(a, b);
- printf("%s(%f, %f) = %f/n", pl->entry, a, b, result);
- //then close it
- code = dlclose(flib);
- dlError = dlerror();
- if(code){
- fprintf(stderr, "close lib error/n");
- g_slist_free(list);
- return -1;
- }
- }
- }
- g_slist_free(list);
- return 0;
- }
首先,定义一个GSList,然后将其传递给load_plugins,load_plugins解析plugin.xml,然后填充list返回,calc_test遍历插件列表,并调用每一个插件定义的entry.
除法器
我们来看一个具体的插件:做除法的模块
- #include <stdio.h>
- double div(double a, double b){
- if(b == 0){
- fprintf(stderr, "div zero error/n");
- return -1;
- }else{
- return a / b;
- }
- }
diver.c在编译之后,生成diver.so,将其置于plugin.xml定义的位置处即可。
运行结果如下图所示:
其他代码如xml的解析,GSList的使用等与插件机制关系不大,感兴趣的朋友可以在附件中查看。
- 【转】C语言插件机制(下)
- C语言插件机制(下)
- C语言插件机制
- 【转】C语言插件机制(上)
- C语言插件机制(上)
- C语言插件机制(上) -- linux动态库
- Linux下C语言开发(信号signal处理机制)
- C语言缓存机制
- C语言struct机制
- c语言return机制
- C语言编程机制
- C语言预处理机制
- c语言缓存机制
- C语言插件开发模式
- C语言中的__attribute__机制
- C语言中的__attribute__机制
- C语言中的__attribute__机制
- Objective-C语言:反射机制
- 常用的C#正则表达式!
- SQLite基本操作加数据库分页查询
- *任意位置浮动固定层
- IRQ和中断号的区别
- Javascript删除节点的全部内容
- 【转】C语言插件机制(下)
- python switch的实现
- nutch1.2 排序
- RDLC Image控件加入图片的几种方式
- 使用Oracle的DBMS_SQL包执行动态SQL语句
- 【转】C语言插件机制(上)
- vb中对ListView的增删改查
- 将类成员函数用做C回调函数
- android 获取手机设备的唯一码(IMIE ) 注册用