第20课 - 链接过程简介
1. 思考一个问题
在具体工作中,每个软件项目都有很多个.c源文件,每个.c源文件经过编译后生成.o格式的目标文件,那么这些.o文件如何生成最终的可执行程序呢?
这里就要引入C语言的链接器了。
2. 链接器的作用
链接器的主要作用就是处理各个模块(目标文件和库文件)之间的相互引用,使得各个模块之间能够正确的衔接。
3. 静态链接
由链接器在链接时将库的内容直接加入到可执行程序中(库中,只有被使用的函数才会被链接进去,未使用的不会被链接到可执行程序中!)。
Linux下静态库的创建和使用:
- 编译静态库源码: gcc -c lib.c -o lib.o
- 生成静态库文件: ar -q lib.a lib.o
- 使用静态库编译: gcc main.c lib.a -o main.out

1 char* name() 2 { 3 return "Static Lib"; 4 } 5 6 7 int add(int a, int b) 8 { 9 return a + b; 10 }

1 #include <stdio.h> 2 3 extern char* name(); 4 extern int add(int a, int b); 5 6 int main() 7 { 8 printf("Name: %s ", name()); 9 printf("Result: %d ", add(2, 3)); 10 11 return 0; 12 }
4. 动态链接
可执行程序在运行时才动态加载库进行链接,库的内容不会进入可执行程序当中。
Linux下动态库的创建和使用:
- 编译动态库源码: gcc -shared -fPIC dlib.c -o dlib.so
- 使用动态库编译: gcc main.c -ldl -o main.out // 使用dlopen、dlsym、dlclose需要用到dl这个动态链接库,-ldl
- 动态库相关的系统调用
— dlopen:打开动态库文件
— dlsym: 查找动态库中的函数并返回调用地址
— dlclose:关闭动态库文件

1 char* name() 2 { 3 return "Dynamic Lib"; 4 } 5 6 int add(int a, int b) 7 { 8 return a + b; 9 }

1 #include <stdio.h> 2 #include <dlfcn.h> 3 4 int main() 5 { 6 void* pdlib = dlopen("./dlib.so", RTLD_LAZY); // 打开动态链接库 7 8 char* (*pname)(); // 定义函数指针 9 int (*padd)(int, int); 10 11 if( pdlib != NULL ) 12 { 13 // 在动态链接库中查找相应的函数入口地址 14 pname = dlsym(pdlib, "name"); 15 padd = dlsym(pdlib, "add"); 16 17 if( (pname != NULL) && (padd != NULL) ) 18 { 19 printf("Name: %s ", pname()); 20 printf("Result: %d ", padd(2, 3)); 21 } 22 23 dlclose(pdlib); // 关闭动态链接库 24 } 25 else 26 { 27 printf("Cannot open lib ... "); 28 } 29 30 return 0; 31 32 }
为什么需要动态链接库呢?
方便程序的更新,当程序有bug或者程序功能需要更新时,不用更新应用程序,只需要更新动态库文件即可,非常方便;如果是静态链接的话无法更新部分应用程序,需要全部重新编译!