Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件。
在链接动态库生成可执行文件时,并不会把动态库的代码复制到执行文件中,而是在执行文件中记录对动态库的引用。
程序执行时,再去加载动态库文件。如果动态库已经加载,则不必重复加载,从而能节省内存空间。
动态库编译方法
示例程序
1
| int add(int a, int b) { return a+b; };
|
1
| gcc -fPIC -shared -o libadd.so add.c
|
动态库加载方式一
1
2
3
4
5
6
7
| #include<stdio.h>
int main(void)
{
add(1,2);
return 0;
}
|
编译时链接
gcc -o main main.c -L . -ladd
直接运行会报错
1
| ./a1.out: error while loading shared libraries: libadd.so: cannot open shared object file: No such file or directory
|
我们有两种方法解决这个问题:
- 将libtest.so库放到系统路径下
- 指定当前进程动态库搜索路径
第一种方法:
1
| $ cp libadd.so /usr/lib
|
第二种方法:
1
| $ export LD_LIBRARY_PATH=./
|
导入LD_LIBRARY_PATH环境变量,指定库搜索路径,使得a.out程序能够找到libadd.so。
动态库加载方式二
采用dlopen
、dlsym
、dlclose
加载动态链接库
dlopen dlclose
1
2
3
4
5
6
7
8
9
10
11
12
| #include <dlfcn.h>
void *dlopen(const char *filename, int flags);
int dlclose(void *handle);
#define _GNU_SOURCE
#include <dlfcn.h>
void *dlmopen (Lmid_t lmid, const char *filename, int flags);
Link with -ldl.
|
dlsym
1
2
3
4
5
6
7
8
9
10
| #include <dlfcn.h>
void *dlsym(void *handle, const char *symbol);
#define _GNU_SOURCE
#include <dlfcn.h>
void *dlvsym(void *handle, char *symbol, char *version);
Link with -ldl.
|
dlerror
1
2
3
4
5
| #include <dlfcn.h>
char *dlerror(void);
Link with -ldl.
|
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| // file : add.c
int add(int a, int b) { return a+b; };
// cmd: gcc -fPIC -shared -o libadd.so add.c
// 编译生成动态库文件
// file : demo.c
#include <stdio.h>
#include <stdlib.h> // EXIT_FAILURE
#include <dlfcn.h> // dlopen, dlerror, dlsym, dlclose
typedef int(* FUNC_ADD)(int, int); // 定义函数指针类型的别名
const char* dllPath = "./libadd.so";
int main()
{
void* handle = dlopen( dllPath, RTLD_LAZY );
if( !handle )
{
fprintf( stderr, "[%s](%d) dlopen get error: %s\n", __FILE__, __LINE__, dlerror() );
exit( EXIT_FAILURE );
}
do{ // for resource handle
FUNC_ADD add_func = (FUNC_ADD)dlsym( handle, "add" );
printf( "1 add 2 is %d \n", add_func(1,2) );
}while(0); // for resource handle
dlclose( handle );
}
// cmd : gcc -o demo demo.c -ldl; ./demo
// output: 1 add 2 is 3
|