您的位置:首页 > 运维架构 > Linux

Linux动态库应用

2015-10-09 23:50 465 查看

Linux动态库应用

Linux动态库应用

简介:

动态库调用方式一

动态库调用方式二

简介:

动态库在编程过程中是一个很重要的技术,在实际开发过程中,我们在设计各模块时,常常会用到一些通用的功能,如文件处理,网络接口等。这时候,我们可以有两种选择:一种是用动态链接技术,一种是静态链接技术。动态链接,顾名思义,就是在程序运行时调用动态库中的函数。静态链接,则是在编译时就已经把代码拷贝到程序中。相比来说,动态库更节省空间与资源,但静态库调用速度更快,因为它是直接编译进程序中;静态库还有一个缺点是当一个静态库被修改时,整个涉及的模块都要重新编译,这对软件更新还说是一个很大的问题,而动态库则只需要更新库文件就可以完成更新。

动态库调用方式一

库函数介绍:
函数原型说明备注
void *dlopen(const char *filename, int flag)该函数将打开一个新库,并把它装入内存头文件:dlfcn.h,编译时需加上-ldl参数(gcc/g++)
char *dlerror(void)库函数报错函数
void *dlsym(void *handle, const char *symbol)获取库符号的地址
void *dlclose(void *handle)关闭库与dlopen对应
设计一个动态库libfunc.so

/****************************func.c***********************************/
#include <stdio.h>

void func()
{
printf("this is call func");
}


/****************************func.h***********************************/

#ifdef __FUNC_H__
#define __FUNC_H__

void func(void);

#endif




用如下命令生成一个动态链接库: 

linux@skytrails$ gcc -shared -fPIC -o libfunc.so func.c


设计调用libfunc.so的主函数:

/****************************main.c***********************************/
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
#include "func.h"
int main() {
void * handle;
void (*pfunc)(void);
char *error;
handle = dlopen("libfunc.so", RTLD_NOW);
if (NULL == handle){
printf("call dlopen failed!");
exit(0);
}
pfunc = (void(*)(void))dlsym(handle, "func");
if (NULL == pfunc){
error = dlerror();
printf("call dlsym failed!%s", error);
}
else{
(*pfunc)();
}
printf("\n");
pfunc = (void(*)(void))dlsym(handle, "func1");
if (NULL == pfunc){
error = dlerror();
printf("call dlsym failed!%s\n", error);
}
else{
(*pfunc)();
}
printf("\n");
pfunc = (void(*)(void))dlsym(handle, "func2");
if (NULL == pfunc){
error = dlerror();
printf("call dlsym failed!%s\n", error);
}
else{
(*pfunc)();
}
printf("\n");
pfunc = (void(*)(void))dlsym(handle, "func3");
if (NULL == pfunc){
error = dlerror();
printf("call dlsym failed!%s\n", error);
}
else{
(*pfunc)();
}
printf("\n");
pfunc = (void(*)(void))dlsym(handle, "func4");
if (NULL == pfunc){
error = dlerror();
printf("call dlsym failed!%s\n", error);
}
else{
(*pfunc)();
}
printf("\n");
exit(1);
}


链接libfunc.so生成可执行文件:

linux@skytrails$ gcc -shared -fPIC main.c -o main -ldl


在命令行下运行可得到:

linux@skytrail$ ./main
call dlsym failed!./libfunc.so: undefined symbol: func
this is call func1
this is call func2
this is call func3
this is call func4


完整的编译可以制作成简易的makefile文件:

################################ makefile文件 ################################
all:libfunc.so main
libfunc.so:func.c func.h
gcc $< -o libfunc.so -fPIC -shared
main:main.c
gcc $< -o main -ldl


注意事项:

调用库函数dlopen,dlsym,dlclose时要加载库libdl.so。

linux为程序动态库提供了5种搜索的路径,系统默认不搜索当前目录,可以根据下文的动态库搜索路径自已选择一种方式,否则找不到指定库文件。

如果把func.c文件后缀改成.cpp,则会以c++方式编译,这时会调用dlsym失败,提示找不到func*符号。这里因为c/c++的差异,需要在函数名前指定为extern "c"。

动态库搜索路径
优先级路径备注
1DT_RPATH(ELF可执行文件中动态段)编译目标代码时,对编译器(gcc/g++)加入链接参数-Wl,-rpath指定动态库搜索路径。优先级最高
2LD_LIBRARY_PATHLinux环境变量
3/etc/ld.so.conf中指定动态库路径不同Linux系统文件不一样(debain)。这里是debain系统
4/lib默认动态为搜索路径
5/usr/lib

动态库调用方式二

简介:

第二种方式其实前面已经应用了。就是libdl.so的调用,在调用库函数dlopen等时需要用到。下面用一个代码实例来说明其应用。

代码示例(libfunc.so库复用上面代码,makefile与main.c作一点小小的修改即可):

/******************************* main.c ******************************/
#include <stdlib.h>
#include <stdio.h>
#include "func.h"
int main() {
func1();
printf("\n");
func2();
printf("\n");
func3();
printf("\n");
func4();
printf("\n");
exit(1);
}


################################ makefile文件 ################################
all:libfunc.so main
libfunc.so:func.c func.h
gcc $< -o libfunc.so -fPIC -shared
main:main.c
gcc $< -o $@ -L. -lfunc


执行make

linux@skytrails$ make
gcc func.c -o libfunc.so -fPIC -shared
gcc main.c -o main -L. -lfunc


执行程序

linux@skytrails$ ./main
this is call func1
this is call func2
this is call func3
this is call func4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: