- 浏览: 583836 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (365)
- Tomcat调优 (2)
- Apache Http (20)
- Webserver安装 (5)
- Linux安装 (28)
- Linux常用命令 (17)
- C语言及网络编程 (10)
- 文件系统 (0)
- Lucene (12)
- Hadoop (9)
- FastDFS (8)
- 报表 (0)
- 性能测试 (1)
- JAVA (18)
- CSharp (3)
- C++ (38)
- BI (0)
- 数据挖掘 (0)
- 数据采集 (0)
- 网址收集整理 (3)
- Resin (0)
- JBoss (0)
- nginx (0)
- 数据结构 (1)
- 随记 (5)
- Katta (1)
- Shell (6)
- webservice (0)
- JBPM (2)
- JQuery (6)
- Flex (41)
- SSH (0)
- javascript (7)
- php (13)
- 数据库 (6)
- 搜索引擎排序 (2)
- LVS (3)
- solr (2)
- windows (1)
- mysql (3)
- 营销软件 (1)
- tfs (1)
- memcache (5)
- 分布式搜索 (3)
- 关注的博客 (1)
- Android (2)
- clucene (11)
- 综合 (1)
- c c++ 多线程 (6)
- Linux (1)
- 注册码 (1)
- 文件类型转换 (3)
- Linux 与 asp.net (2)
- perl (5)
- coreseek (1)
- 阅读器 (2)
- SEO (1)
- 励志 (1)
- 在线性能测试工具 (1)
- yii (7)
- 服务器监控 (1)
- 广告 (1)
- 代理服务 (5)
- zookeeper (8)
- 广告联盟 (0)
- 常用软件下载 (1)
- 架设自已的站点心得 (0)
最新评论
-
terry07:
java 7 用这个就可以了 Desktop desktop ...
关于java Runtime.getRunTime.exec(String command)的使用 -
HSINKING:
怎么设置打开的dos 窗口是指定的路径下
关于java调用bat文件,不打开窗口 -
liubang201010:
hyperic hq更多参考资料,请访问:http://www ...
hyperic-hq -
^=^:
STDIN_FILENO是unistd.h中定义的一个numb ...
深入理解dup和dup2的用法 -
antor:
留个记号,学习了
[转]用java流方式判断文件类型
[img][/img]http://www.iteye.com/topic/747159
前言
上一篇文章简单介绍了*NIX下的动态库的使用,我们在这篇文章中实现一个计算器,计算器程序calc本身不做运算,只是将操作数传递给具体的插件(adder, suber, muler, diver)来完成实际运算。首先,计算器根据插件配置文件plugin.xml来确定插件的位置,名称,入口符号的定义,然后依次调用各个插件完成计算。
插件列表
文中涉及到的插件定义在plugin.xml中,文档结构如下:
Xml代码
每个插件为一个plugin标签,plugin标签中包含library, entry两个字标签,分别定义动态库文件的路径及名称和插件函数的入口。为了简便,我们不重复设计list及xml解析,这里使用libxml2作为xml的分析器,GLIB中的GSList(单链表)来作为插件列表的链表对象。
每一个插件在C语言中的定义如下,非常简单(plugin.h)
C代码
这里为了行文方便,Plugin结构中的字符串为静态尺寸。
计算器
计算器调用parseconf模块中的load_plugins将plugin.xml中定义的Plugin加载进一个GSList,以备后用:
C代码
插件中的函数原型应该符合接口定义:
C代码
计算器的主要代码如下:
C代码
首先,定义一个GSList,然后将其传递给load_plugins,load_plugins解析plugin.xml,然后填充list返回,calc_test遍历插件列表,并调用每一个插件定义的entry.
除法器
我们来看一个具体的插件:做除法的模块
C代码
运行结果如下图所示:
其他代码如xml的解析,GSList的使用等与插件机制关系不大,感兴趣的朋友可以在附件中查看。
前言
上一篇文章简单介绍了*NIX下的动态库的使用,我们在这篇文章中实现一个计算器,计算器程序calc本身不做运算,只是将操作数传递给具体的插件(adder, suber, muler, diver)来完成实际运算。首先,计算器根据插件配置文件plugin.xml来确定插件的位置,名称,入口符号的定义,然后依次调用各个插件完成计算。
插件列表
文中涉及到的插件定义在plugin.xml中,文档结构如下:
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> <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)
C代码
#ifndef _PLUGIN_H_ #define _PLUGIN_H_ typedef struct{ char name[64]; char path[256]; char entry[128]; int version; }Plugin; #endif #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,以备后用:
C代码
#include "plugin.h" extern int load_plugins(char *config, GSList **list); #include "plugin.h" extern int load_plugins(char *config, GSList **list);
插件中的函数原型应该符合接口定义:
C代码
//pointer to function, which return a double, and get 2 double as input double (*pfunc)(double a, double b); //pointer to function, which return a double, and get 2 double as input double (*pfunc)(double a, double b);
计算器的主要代码如下:
C代码
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; } 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.
除法器
我们来看一个具体的插件:做除法的模块
C代码
#include <stdio.h> double div(double a, double b){ if(b == 0){ fprintf(stderr, "div zero error\n"); return -1; }else{ return a / b; } } #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的使用等与插件机制关系不大,感兴趣的朋友可以在附件中查看。
- calc.rar (204.9 KB)
- 下载次数: 0
- calc.tar.gz (12.4 KB)
- 下载次数: 2
发表评论
-
深入理解dup和dup2的用法
2011-08-15 11:02 12010引用网上有很多资料详 ... -
Linux下进程绑定多CPU运行
2011-06-10 12:28 2060引用Published on 十二月 17, 2009 2,3 ... -
Visual Studio 2010 编译C及一个完整的c程序(可在windows与linux(用gcc编译)平台下使用)
2011-01-25 13:29 3269中科院分词linux版破解过程 中科院分词linux版破解 ... -
muduo 与 libevent2 吞吐量对比
2010-09-08 14:43 1759http://blog.csdn.net/Solstice/a ... -
C语言插件机制(上)
2010-09-06 14:08 1001http://abruzzi.iteye.com/blog/7 ... -
Linux 网络编程 <1>
2010-07-05 17:37 1077环境 Cygwin+windows2003 说明: 服务 ... -
用程序生成swf(flash)文件: ming 和 swftools
2010-05-25 13:40 1828用程序生成swf(flash)文件: ming 和 swfto ... -
linux fork函数学习
2010-05-23 00:55 1491在编写socket ftp之前,我对fork函数进行了学习。 ... -
gdb 子进程 多进程 fork 调试
2010-05-21 17:28 2092标 题: [FAQ] 请问如何用gdb调试子进程 发信站 ...
相关推荐
C语言插件通常是指在开发环境中为了增强对C语言支持而设计的工具或组件。这些插件可能提供语法高亮、自动补全、调试功能、代码分析等特性,以提升C程序员的开发效率和代码质量。 在C语言的开发过程中,一些关键知识...
本文将深入探讨如何利用CDT插件在Eclipse中构建C语言的编译环境,以及相关辅助工具和配置技巧。 首先,CDT插件提供了代码编辑、调试、构建系统等一站式服务。安装CDT后,用户可以在Eclipse内直接编写、编译和运行C/...
Sublime Text 3 是一款功能强大且广受欢迎的代码编辑器,它的插件机制使得用户可以根据需要安装各种插件以满足不同的需求。本文将详细介绍 Sublime Text 3 插件的安装方法,并以 Emmet 插件为例展示插件的安装和...
4.3 异常处理:使用`try-catch`机制或自定义错误处理流程,确保程序在异常情况下能正常退出。 五、模块化与可扩展性 5.1 封装原则:将功能相近的代码组织在一起,提高代码复用性。每个源文件只包含一个主要功能。 ...
在IT领域,尤其是在多媒体处理和流媒体应用中,GStreamer是一个强大的开源框架,它允许开发者构建复杂的...通过深入研究源代码和GStreamer插件机制,开发者可以进一步定制和优化这个插件,以满足特定应用场景的需求。
2. **DLL项目设置**:在C语言环境下,如Visual Studio,你需要创建一个Win32 DLL项目。在项目属性中,配置生成动态链接库的目标类型,并确定所需的API和头文件。 3. **导出函数**:在C语言中,使用`__declspec(dll...
7. **动态库和插件机制**:Snort允许用户通过动态加载库(插件)来扩展其功能,比如添加新的检测规则、日志格式或协议解析器。 8. **性能优化**:为了处理海量网络流量,Snort使用了多种优化技术,如多线程处理、...
C语言本身并不直接支持面向对象编程,但通过巧妙的设计,可以模拟出类似的功能,构建出强大的框架系统和插件机制。本资源"book_cprogramming"可能是一个教程或代码示例集,旨在帮助开发者理解和掌握这一技术。 一、...
“软件/插件”可能暗示着这不只是一个简单的程序,它可能包含了一些特定的库或者插件,如EasyX,以增强其功能。“范文/模板/素材”则表明这个项目可以作为一个学习的样本,或者是开发者创建类似游戏时可以参考的模板...
5. **内存管理**:C语言没有自动垃圾回收机制,所以开发者需要手动分配和释放内存。在创建和删除蛇的节点时,要特别注意内存泄漏问题。 6. **屏幕绘图**:在C语言中,可以使用ANSI转义码或者`ncurses`库来在终端上...
5. 并发控制:尽管这是一个单用户系统,但源码可能包含了一些并发控制的概念,如锁或其他同步机制,以模拟多用户环境下可能遇到的问题。 6. 日志记录:可能包含简单的日志记录功能,用于追踪系统的运行状态和用户...
创建两个线程分别控制两条蛇,通过同步机制(如互斥锁或条件变量)保证游戏逻辑的正确性,防止并发冲突。 【游戏逻辑与算法】 贪吃蛇游戏的逻辑包括蛇的移动、食物生成、碰撞检测和游戏结束条件判断。其中,移动...
现在,尽管宽带连接更为常见,但PPP在某些场景下仍然有用,例如在路由器配置、远程访问服务器和物联网设备中。 首先,让我们深入了解PPP协议。PPP协议主要由三部分组成:链路控制协议(LCP)、网络控制协议(NCP)...
标题中的“C语言环境下别踩白块儿(双人版)源码.zip”指的是一个使用C语言编写的,适用于双人游戏的“别踩白块儿”程序的源代码文件。这种游戏通常要求玩家在黑色方块上点击,避免触碰到白色的方块,以测试反应速度...
学习PLL的C语言实现和仿真,有助于初学者理解PLL的工作机制,提高分析和设计能力。通过编程实现,可以更直观地看到PLL如何响应不同输入信号,以及在不同参数设置下的行为,这对于理解和优化PLL系统至关重要。 5. ...
10. 可扩展性:可扩展性是日历系统的重要特征之一,需要使用C语言实现可扩展机制,包括插件机制、接口机制等。 11. 可维护性:可维护性是日历系统的重要特征之一,需要使用C语言实现可维护机制,包括日志机制、错误...
8. 用户界面:虽然C语言本身不支持图形用户界面(GUI),但在命令行环境下,可以设计简单的文本交互界面,通过获取用户输入的命令来执行相应的功能。 9. 测试与调试:完成编码后,需要对系统进行详尽的测试,确保...
4. 错误处理:C语言提供了丰富的错误处理机制,如设置errno变量、使用异常处理函数等,确保在遇到问题时,系统能够给出适当的反馈,而不是崩溃。 5. 文件操作:图书信息通常存储在文件中,C语言的文件操作函数(如...
标签为"软件/插件 c语言 游戏",这进一步明确了我们要探讨的内容。C语言在游戏开发中通常用于编写底层逻辑和高性能部分,而“软件/插件”则可能指的是游戏的可扩展性和模块化设计。 在压缩包内,我们找到了名为“纯...