动态库简介
动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部分,而是根据执行程序需要按需装入,同时其执行代码可在多个执行程序间共享,节省了空间,提高了效率,具备很高的灵活性。
编写一个简单的动态库
my_so.c
#include <stdio.h>
#include <stdlib.h>
int global = 0xAA55;
void my_printf_str(char *s)
{
printf("@@! test by vincent\n");
printf("%s\n",s);
}
void my_printf_int(int c)
{
printf("@@# test by vincent\n");
printf("0x%08X\n",c);
}
linux命令下执行如下命令编译,注意一些编译选项:
gcc -fpic -shared -o my_so.so my_so.c
-fpic 使输出的对象模块是按照可重定位地址方式生成的。
-shared指定把对应的源文件生成对应的动态链接库文件libstr.so文件。
关于如果使用动态库
Linux下使用动态链接库,源程序需要包含dlfcn.h头文件,此文件定义了调用动态链接库的函数的原型。下面介绍动态库使用中两个重要函数:
1原型:
- void *dlopen (const char *filename, int flag);
dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。
参数说明:
filename: so文件名.如果名字不以/开头,则非绝对路径名,将按下列先后顺序查找该文件。
(1) 用户环境变量中的LD_LIBRARY值;
(2) 动态链接缓冲文件/etc/ld.so.cache
(3) 目录/lib,/usr/lib.
flag:表示在什么时候解决未定义的符号(调用)。取值有两个:
1) RTLD_LAZY : 表明在动态链接库的函数代码执行时解决。
2) RTLD_NOW : 表明在dlopen返回前就解决所有未定义的符号,一旦未解决,dlopen将返回错误。
dlopen调用失败时,将返回NULL值,否则返回的是操作句柄。
2原型:
- void *dlsym(void *handle, char *symbol);
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。由此地址,可以带参数执行相应的函数。
使用动态库的一个简单应用例程:
test_so_app.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void main(void)
{
void *handler = NULL ;
void (*method1)(char *ptr);
void (*method2)(int x);
int *method3 = NULL;
handler =dlopen("/media/workspace/vincent/develop/app/so_test/my_so.so",RTLD_LAZY);
if (!handler)
{
printf( "Load [ERROR]%s\n", dlerror() );
return;
}
method1 = dlsym(handler,"my_printf_str");
method2 = dlsym(handler,"my_printf_int");
method3 = dlsym(handler,"global");
/* export a function */
if(method1)
method1("hello share so");
/* export a function */
if(method2)
method2(0x55);
/* export a golbal variable */
if(method3)
printf("0x%08X\n",*method3);
dlclose(handler);
}
在Linux命令行执行如下命令编译:
gcc -ldl -o so_test_app so_test_app.c
运行程序验证,程序正确输出如下:
vincent@fwtdev2:/media/workspace/vincent/develop/app/so_test$ ./so_test_app
@@! test by vincent
hello share so
@@# test by vincent
0x00000055
0x0000AA55