锁定老帖子 主题:C语言插件机制(上)
精华帖 (9) :: 良好帖 (3) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-08-17
前言插件机制可以使得应用程序在发布之后,在不经过重新编译的情况下修改应用程序的行为,这种形式使得应用的框架比较小巧,也可以给用户一些自由(不是完全的自由,有一定的限制)。Java中,使用*.jar或者其他的脚本引擎都可以完成这样的工作,如Eclipse那样。在C语言中,当然可以使用脚本引擎来实现,比如emacs,内置一个lisp的引擎,用户可以自己为emacs写脚本,访问emacs环境的一些组件,从而定制emacs.这里要讨论的无需使用脚本引擎,而是用C语言访问动态链接库来实现。 Linux下的动态库Linux环境中,与windows下一样,函数库有两种方式:静态库和动态库,静态库参与连接,由于要将目标代码.o与lib中的函数符号合并在一起,所以最终生成的可执行文件较大。一般以.a结尾。如libxxx.a。而动态库(共享库)则不参与编译,只是在运行时才加载如内存,且仅加载一次,因此最终的可执行文件较小。事实上,当一个可执行文件需要运行动态库中的函数时,系统会在内存中查找,如果已经加载,则直接调用,否则才做一次加载,动态库的结尾一般为.so,如libxxx.so。
Linux为动态库的访问提供了4个API,分别为
动态库的使用较为简单,比如动态库的名称为plugina.so,其中包含这样的函数原型:
int func(int a, int b); 可以看下一个例子:
#include <dlfcn.h> //句柄 void *flib; //入口函数原型 int (*pfunc)(int a, int b); //错误信息字符串 char *error_message; int plugin_test(){ int a = 1, b = 4; int result = 0; //加载plugina.so,以RTLD_LAZY方式 flib = dlopen("/home/juntao/.libs/plugina.so", RTLD_LAZY); error_message = dlerror(); if(error_message){ return (-1); } //找到函数名为func的函数,返回其指针 *(void **)(&pfunc) = dlsym(flib, "func"); error_message = dlerror(); if(error_message){ return (-1); } //调用pfunc指向的指针,及func函数 result = pfunc(a, b); //释放 int code = dlclose(flib); error_message = dlerror(); if(error_message){ return (-1); } return 0; } 编译运行假设plugina.so的源文件为plugina.c,内容为:
//file plugina.c int func(int a, int b){ int c = 0; c = 3*a + 4*b + 6; return c; }
我们将这个.c文件编译为.so,命令如下:
//生成plugina.o
$gcc -c -fpic plugina.c //生成plugina.so $gcc -shared -lc -o plugina.so plugina.o
将动态库访问部分的代码存为plugintest.c,然后使用下列命令编译:
$gcc -o plugintest plugintest.c -ldl
-ldl意思是,使用库libdl.so,linux下访问搜索路径内的库文件无需加lib前缀。
将生成的plugina.so放入路径/home/juntao/.libs/,然后运行plugintest。
$./plugintest result = 25
好了,这一次先介绍一些基础知识,相信在此基础上,很多朋友都可以自己设计出一些简单实用的支持“插件”的应用来了,我们下一次详细讨论一个更实际一些的例子,一个计算器的实现,这个计算器只有简单的框剪,所有的运算都通过插件来实现。用户可以通过配置文件来定制插件的路径,入口等信息。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-09-01
最近爱上c 了
|
|
返回顶楼 | |
发表时间:2010-09-01
不错~没试过,回去试试~
|
|
返回顶楼 | |
浏览 4961 次