动态库调用的那些事

调用动态库的两种方式

1. 类似静态库—-头文件

这种方式生成的程序会在启动时候就加载so动态库。

1
2
//add.h
int add(int x, int y)
1
2
3
4
//add.c
int add(int x, int y){
return x + y;
}
1
2
3
4
5
6
7
8
9
10
//main.c
#include <stdio.h>
#include "add.h"

int main(){
int sum = add(7, 8);
printf("7+8 = %d\n", sum);

return 0;
}

编译生成libadd.so

1
gcc -shared -fPIC -o libadd.so add.c

编译main,使用-L./指定add库在当前目录。

1
gcc -o main main.c -L./ -ladd

此时如果不使用-L来指定动态库路径的话, 可以使用LIBRARY_PATH

1
export LIBRARY_PATH=LIBDIR1:LIBDIR2:$LIBRARY_PATH

2. 使用dlopen/dlsum动态加载动态库—-不使用头文件

这种方式生成的程序会在代码执行到指定行位置加载so动态库。

1
2
3
4
//add.c
int add(int x, int y) {
return (x + y);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//main.c
#include <stdio.h>
#include <dlfcn.h>

int main(){
/*手动加载指定位置的so动态库*/
void* handle = dlopen("./libadd.so", RTLD_LAZY);
int (*add)(int a, int b);

/*根据动态链接库操作句柄与符号,返回符号对应的地址*/
add = dlsym(handle, "add");

int sum = add(7, 8);
printf("7+8 = %d\n", sum);

dlclose(handle);
return 0;
}

编译so,生成libadd.so

1
gcc -shared -fPIC -o libadd.so add.c

编译main,不需要指定libadd.so相关信息进行编译,执行时候会在指定目录加载

1
gcc -o main main.c -ldl

一般需要添加LD_LIBRARY_PATH

LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径

1
export LD_LIBRARY_PATH=LIBDIR1:LIBDIR2:$LD_LIBRARY_PATH