http://abruzzi.iteye.com/blog/739673
2010-08-17
C语言插件机制(上)
文章分类:C++编程
前言
插件机制可以使得应用程序在发布之后,在不经过重新编译的情况下修改应用程序的行为,这种形式使得应用的框架比较小巧,也可以给用户一些自由(不是完全的自由,有一定的限制)。Java中,使用*.jar或者其他的脚本引擎都可以完成这样的工作,如Eclipse那样。在C语言中,当然可以使用脚本引擎来实现,比如emacs,内置一个lisp的引擎,用户可以自己为emacs写脚本,访问emacs环境的一些组件,从而定制emacs.这里要讨论的无需使用脚本引擎,而是用C语言访问动态链接库来实现。
Linux下的动态库
Linux环境中,与windows下一样,函数库有两种方式:静态库和动态库,静态库参与连接,由于要将目标代码.o与lib中的函数符号合并在一起,所以最终生成的可执行文件较大。一般以.a结尾。如libxxx.a。而动态库(共享库)则不参与编译,只是在运行时才加载如内存,且仅加载一次,因此最终的可执行文件较小。事实上,当一个可执行文件需要运行动态库中的函数时,系统会在内存中查找,如果已经加载,则直接调用,否则才做一次加载,动态库的结尾一般为.so,如libxxx.so。
Linux为动态库的访问提供了4个API,分别为dlopen , dlerror , dlsym 和 dlclose。这些API的原型定义在文件dlfcn.h中,其实现则分别对应有两个库文件(静态库 libdl.a 和动态库 libdl.so)。
dlopen加载动态库,并返回句柄
dlerror如果加载,访问符号出错,可以通过此接口获得详细的描述
dlsym返回一个动态库中的符号,即通过函数名获得此函数的指针
dlclose完成之后,释放dlopen返回的句柄
动态库的使用较为简单,比如动态库的名称为plugina.so,其中包含这样的函数原型:
C代码
int func(int a, int b);
int func(int a, int b
);
可以看下一个例子:
C代码
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;
}
#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,内容为:
C代码
//file plugina.c
int func(int a, int b){
int c = 0;
c = 3*a + 4*b + 6;
return 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,然后使用下列命令编译:
C代码
$gcc -o plugintest plugintest.c -ldl
$gcc -o plugintest plugintest.c -ldl
-ldl意思是,使用库libdl.so,linux下访问搜索路径内的库文件无需加lib前缀。
将生成的plugina.so放入路径/home/juntao/.libs/,然后运行plugintest。
$./plugintest
result = 25
好了,这一次先介绍一些基础知识,相信在此基础上,很多朋友都可以自己设计出一些简单实用的支持“插件”的应用来了,我们下一次详细讨论一个更实际一些的例子,一个计算器的实现,这个计算器只有简单的框剪,所有的运算都通过插件来实现。用户可以通过配置文件来定制插件的路径,入口等信息。
分享到:
相关推荐
在本篇中,我们将深入探讨"C语言插件机制(下)"这一主题,主要关注如何在C语言中实现插件系统,以及与之相关的工具和技术。首先,插件机制是一种允许程序在运行时动态加载和卸载附加功能的方式,它极大地提高了软件的...
C语言插件通常是指在开发环境中为了增强对C语言支持而设计的工具或组件。这些插件可能提供语法高亮、自动补全、调试功能、代码分析等特性,以提升C程序员的开发效率和代码质量。 在C语言的开发过程中,一些关键知识...
综上所述,CDT插件让Eclipse成为一个全面的C/C++开发环境,无论是在Windows下使用MinGW、Visual Studio还是其他编译器,都能提供强大的支持。同时,掌握Makefile的编写技巧和高精度计时方法,有助于提升开发效率和...
Sublime Text 3 是一款功能强大且广受欢迎的代码编辑器,它的插件机制使得用户可以根据需要安装各种插件以满足不同的需求。本文将详细介绍 Sublime Text 3 插件的安装方法,并以 Emmet 插件为例展示插件的安装和...
4.3 异常处理:使用`try-catch`机制或自定义错误处理流程,确保程序在异常情况下能正常退出。 五、模块化与可扩展性 5.1 封装原则:将功能相近的代码组织在一起,提高代码复用性。每个源文件只包含一个主要功能。 ...
在IT领域,尤其是在多媒体处理和流媒体应用中,GStreamer是一个强大的开源框架,它允许开发者构建复杂的...通过深入研究源代码和GStreamer插件机制,开发者可以进一步定制和优化这个插件,以满足特定应用场景的需求。
7. **动态库和插件机制**:Snort允许用户通过动态加载库(插件)来扩展其功能,比如添加新的检测规则、日志格式或协议解析器。 8. **性能优化**:为了处理海量网络流量,Snort使用了多种优化技术,如多线程处理、...
C语言本身并不直接支持面向对象编程,但通过巧妙的设计,可以模拟出类似的功能,构建出强大的框架系统和插件机制。本资源"book_cprogramming"可能是一个教程或代码示例集,旨在帮助开发者理解和掌握这一技术。 一、...
“软件/插件”可能暗示着这不只是一个简单的程序,它可能包含了一些特定的库或者插件,如EasyX,以增强其功能。“范文/模板/素材”则表明这个项目可以作为一个学习的样本,或者是开发者创建类似游戏时可以参考的模板...
5. **内存管理**:C语言没有自动垃圾回收机制,所以开发者需要手动分配和释放内存。在创建和删除蛇的节点时,要特别注意内存泄漏问题。 6. **屏幕绘图**:在C语言中,可以使用ANSI转义码或者`ncurses`库来在终端上...
7. **错误处理**:在源码中,错误处理机制是必不可少的,它可以帮助程序在遇到问题时优雅地退出,而不是崩溃。通常会使用assert宏或自定义错误处理函数。 8. **优化与调试**:游戏源码中还可能包含一些性能优化的...
2. **错误检测**:SLIP不提供内置的错误检测机制,如校验和或循环冗余校验(CRC)。这通常需要在应用层或更高层次协议中处理。 3. **数据透明性**:SLIP协议能够传输任何8位字节的数据,因为它能编码特殊字符,确保...
而在易语言中,可能需要通过自定义异常机制来捕获和处理错误。 8. **调试与测试**:编写好DLL后,需要在C语言环境中进行单元测试,确保函数逻辑正确。然后在易语言环境中调用这些函数,进行集成测试,确保两者间的...
“软件/插件”标签则意味着这是一个完整的可执行程序,而不是库或框架的一部分,可以直接运行在支持C语言的环境中。 【源码文件列表】:虽然具体文件名未知,但常见的源码结构可能包括以下几个部分: 1. 主程序...
贪吃蛇游戏是一款经典的电子游戏,最早出现在早期的诺基亚手机上,后来逐渐发展到各种平台,包括个人电脑。它以其简单易懂的规则和高度可玩性深受玩家喜爱。在C语言实现的双人对战版中,玩家可以控制两条蛇进行竞争...
4. **ppp chap**: CHAP(Challenge Handshake Authentication Protocol)实现,提供安全的认证机制。 5. **ppp pap**: PAP(Password Authentication Protocol)的实现,较不安全,但更简单。 6. **配置文件和脚本**...
10. 可扩展性:可扩展性是日历系统的重要特征之一,需要使用C语言实现可扩展机制,包括插件机制、接口机制等。 11. 可维护性:可维护性是日历系统的重要特征之一,需要使用C语言实现可维护机制,包括日志机制、错误...
学习PLL的C语言实现和仿真,有助于初学者理解PLL的工作机制,提高分析和设计能力。通过编程实现,可以更直观地看到PLL如何响应不同输入信号,以及在不同参数设置下的行为,这对于理解和优化PLL系统至关重要。 5. ...
标签为"软件/插件 c语言 游戏",这进一步明确了我们要探讨的内容。C语言在游戏开发中通常用于编写底层逻辑和高性能部分,而“软件/插件”则可能指的是游戏的可扩展性和模块化设计。 在压缩包内,我们找到了名为“纯...
4. 错误处理:C语言提供了丰富的错误处理机制,如设置errno变量、使用异常处理函数等,确保在遇到问题时,系统能够给出适当的反馈,而不是崩溃。 5. 文件操作:图书信息通常存储在文件中,C语言的文件操作函数(如...