前言
上一篇文章简单介绍了*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的使用等与插件机制关系不大,感兴趣的朋友可以在附件中查看。
- 大小: 14.5 KB
分享到:
相关推荐
NULL 博文链接:https://sealbird.iteye.com/blog/756577
它包含了完整的游戏逻辑和界面设计,可以帮助我们深入理解华容道的运行机制,以及如何在计算机程序中实现这种机制。这份资料包的内容丰富,包括了华容道游戏的初始化、方块的移动、判断游戏是否胜利等核心功能。同时...
同时,该系统可能还包括了错误处理机制,让用户能够更好地理解如何确保程序的健壮性和稳定性。对于正在学习C语言编程的学生来说,通过分析和运行这个图书借阅系统的源码,可以加深对C语言语法的理解,提升编程技巧,...
此外,系统还考虑到了数据的安全性和完整性,通过适当的错误处理和验证机制,确保了数据的准确性和可靠性。 值得一提的是,这套C语言学生成绩管理系统源码资源不仅具有高度的实用性,还具备很强的可扩展性和可定制...
基于epoll机制的高并发聊天室,c语言实现 - 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! 1、该资源内...
相比非阻塞忙轮询这类无差别轮训,linux内核提供了epoll这样更高级的形式 把需要处理的IO事件添加到epoll内核列表,epoll_wait来监控并提醒用户程序当IO事件发生时 此聊天室客户端代码fork两个进程,子进程把用户...
以下是对C语言条形码识别的描述,不包含具体的代码实现: 图像处理:条形码识别首先需要对输入的图像进行预处理。这包括图像的二值化、去噪和增强等操作,以提高条形码的边缘清晰度和对比度。 条形码定位:在...
吞噬成长机制:通过吞噬地图中的小颗粒使球球不断变大,以达成更高分数。 ai小球设置:地图内设有多个ai小球,它们可以根据自身的大小和与玩家的距离来选择追击玩家或者逃跑,增加游戏的趣味性。 积分系统:设立...
4. **游戏机制与玩法**: - 玩家需要定时给作物浇水,保持土壤湿润度。 - 可能包含升级系统,如改进灌溉设备以提高浇水效率。 - 游戏内可能设有任务系统,完成任务获得奖励或解锁新作物。 - 可能存在经济系统,...
Spring框架负责业务逻辑处理,通过SpringMVC实现高效的请求处理机制。 MyBatis用于数据库操作,简化数据持久化过程,提高系统性能。 实现RESTful API,确保前后端分离,提高系统的可维护性和可扩展性。 数据库设计:...
游戏保留了经典推箱子游戏的核心玩法,即推动箱子到指定位置,但在此基础上加入了众多创新元素和机制,使得游戏更加丰富和有趣。 二、核心玩法与特色 多样化的关卡设计:每个关卡都有独特的布局和难度,需要玩家运用...
设计敌方坦克生成和控制机制,包括生成位置、难度递增等。 实现碰撞检测,包括坦克与子弹、坦克与障碍物等的碰撞判断。 关卡设计: 设计关卡地图,包括障碍物的位置、敌方坦克的生成等。 设计关卡目标和胜利条件,...
C语言实现基于Risc-V 的操作系统内核模拟设计与实现源代码,一个运行在RISC-V架构处理器上的玩具嵌入式操作系统 完成了操作系统的引导、UART 串口驱动、中断管理、动态内存管理、多任务调度、自旋锁、信号量、FAT32...
其特点包括清晰的代码结构、高效的数据库访问、安全的用户认证和授权机制、响应式布局以适应不同设备、友好的用户界面等。这些项目源码还提供了丰富的功能模块和插件,支持用户管理、权限控制、数据可视化、电子支付...
本课程为《C语言嵌入式Linux编程》第3期,主要对程序的编译、链接及运行机制进行分析。同时对静态库链接、动态链接的过程、插件原理、内核模块运行机进行探讨,后对嵌入式系统比较难理解的u-boot重定位、u-boot加载...
Lua 教程 lua Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用...扩展和数据库插件如:MySQL Proxy 和 MySQL WorkBench 安全系统,如入侵检测系统
FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。 FastDFS架构 FastDFS架构...
Ceedling还可以通过方便的插件机制进行扩展。 使用说明文件 文档和许可证信息存在 入门 首先,请确保Ruby已安装在您的系统上(如果尚未安装)。 然后,在命令提示符下: > gem install ceedling (为打算成为开发...
健壮性:java的健壮性与自动垃圾回收机制有关,自动垃圾回收机制简称GC机制,java语言运行过程中产生的垃圾是自动回收的,不需要程序员关心。 可移植性:java程序可以做到一次编译,到处运行。在Windows操作系统上...
UML StateWizard for VS.NET/VC6/EVC4可为嵌入式系统或Win32/WinCE开发带来可视化、基于可移植C语言的UML状态机编程机制。同时,作为Visual C++的插件,它使得开发者可以在强大的Visual C++开发环境中进行嵌入式系统...