一个可执行程序可能与多个动态库有关联,通常是在程序运行时将必要的动态库装载入进程实体(内存中);
另外一种,则是使用dlopen/dlsym/dlclose来动态地将动态库装载到当前进程实体中.
简单点说,就是:
1.dlopen将指定的动态库以特定的方式装载到当前进程实体,并返回一个可操作的句柄,用以后续获取函数地址等操作;
2.dlsym从指定的(由dlopen的返回值指定)库中获得指定的函数(第二个参数为函数名);
3.dlclose可将关闭卸载动态库;注意,实际是减掉一个对动态库的引用(ref),仅当减到0时才会触发卸载动态库的操作;
4.dlerror返回一个字符串用以描述错误;
通常的三段式就是:先打开(dlopen),然后获得需要的函数(dlsym),然后调用函数,最后关闭(dlclose)
示例:
动态库:
count.h
#ifndef _COUNT_H
#define _COUNT_H
int count;
int get();
void inc();
#endif
count.c
#include "count.h"
int get()
{
return count;
}
void inc()
{
count++;
}
编译动态库:
[test1280@localhost ~]$ gcc -fPIC -c count.c
[test1280@localhost ~]$ gcc -shared -fPIC -o libcount.so *.o
[test1280@localhost ~]$ ll
total 20
-rw-rw-r--. 1 test1280 test1280 76 Oct 21 04:43 count.c
-rw-rw-r--. 1 test1280 test1280 77 Oct 21 04:42 count.h
-rw-rw-r--. 1 test1280 test1280 1568 Oct 21 04:56 count.o
-rwxrwxr-x. 1 test1280 test1280 7913 Oct 21 04:57 libcount.so
dlopen/dlsym/dlclose使用示例:
#include <stdio.h>
#include <dlfcn.h>
#define NUM 6
#define LIBPATH "/home/test1280/libcount.so"
int main()
{
void *handler = dlopen(LIBPATH, RTLD_LAZY);
if (handler == NULL)
{
printf("ERROR:%s:dlopen\n", dlerror());
return -1;
}
void (*inc)() = (void (*)())dlsym(handler, "inc");
if (inc == NULL)
{
printf("ERROR:%s:dlsym\n", dlerror());
return -1;
}
int i = 0;
for (; i < NUM; i++)
inc();
int (*get)() = (int (*)())dlsym(handler, "get");
if (get == NULL)
{
printf("ERROR:%s:dlsym\n", dlerror());
return -1;
}
printf("INFO:get() return %d\n", get());
dlclose(handler);
return 0;
}
编译:
[test1280@localhost ~]$ gcc -o main main.c -ldl
注意:
源文件中没有包含count.h头文件;
编译时没有使用-l指定libcount.so;
dlfcn.h是dlopen的头文件,调用时要加-ldl参数
[test1280@localhost ~]$ ll
total 36
-rw-rw-r--. 1 test1280 test1280 76 Oct 21 04:43 count.c
-rw-rw-r--. 1 test1280 test1280 77 Oct 21 04:42 count.h
-rw-rw-r--. 1 test1280 test1280 1568 Oct 21 04:56 count.o
-rwxrwxr-x. 1 test1280 test1280 7913 Oct 21 04:57 libcount.so
-rwxrwxr-x. 1 test1280 test1280 8761 Oct 21 05:12 main
-rw-rw-r--. 1 test1280 test1280 620 Oct 21 05:11 main.c
再多测试下dlerror:
给出一个不存在的动态库路径:
#define LIBPATH "/home/test1280/libcount1.so"
[test1280@localhost ~]$ ./main
ERROR:/home/test1280/libcount1.so: cannot open shared object file: No such file or directory:dlopen
给出不存在的函数名称:
void (*inc)() = (void (*)())dlsym(handler, "inc_test1280");
[test1280@localhost ~]$ ./main
ERROR:/home/test1280/libcount.so: undefined symbol: inc_test1280:dlsym