- 连接器的主要做用是把各个模块之间互相引用的部分处理好,使得各个模块之间可以正确的衔接。
- 由连接器在连接时将库的内容直接加入到可执行文件中
- 编译静态库源码: gcc-c lib.c -o lib.o
- 生成静态库文件: ar -q lib.a lib.o
- 使用静态库编译: gcc main.c lib.a -o main.out
test.c
#include <stdio.h> extern char* name(); extern int add(int a, int b); int main() { printf("Name" %s\n", name()); printf("Result: %d\n", add(2, 3)); return 0; }
slib.c
char* name() { return "Static Lib"; } int add(int a, int b) { return a + b; }
输出: Name Static Lib Result: 5 gcc -c slib.c -o slib.o ar -q slib.a -o slib.o gcc test.c slib.a -o test.out
- 可执行程序在运行时才动态加载库进行连接
- 库的内容不会进入可执行程序当中
stubx : 告诉编译器动态库中可以使用的内容编程
- 编译动态库源码: gcc -shared dlib.c -o dlib.so
- 使用动态库编译: gcc main.c -ldl -o main.out
关键系统调用函数
- dlopen: 打开动态库文件
- dlsym: 查找动态库中的函数并返回调用地址
- dlclose: 关闭动态库文件
test.c
#include <stdio.h> #include <dlfcn.h> extern char* name(); extern int add(int a, int b); int main() { void* pdlib = dlopen("./dlib.so", RTLD_LAZY); char* (*pname)(); int (*padd)(int, int); if( pdlib != NULL ) { pname = dlsym(pdlib, "name"); padd = dlsym(pdlib, "add"); if( (pname != NULL) && (padd != NULL) ) { printf("Name %s\n", pname()); printf("Result: %d\n", padd(2, 3)); } dlclose(pdlib); } else { printf("Cannot open lib ... \n"); } return 0; }
dlib.c
char* name() { return "Static Lib"; } int add(int a, int b) { return a + b; }
输出: Name Static Lib Result: 5 gcc -shared dlib.c -o dlib.so gcc test.c -ldl -o test.out
- 连接是指将目标文件最终连接为可执行文件
根据连接方式的不一样,连接过程能够分为:spa
- 静态连接: 将目标文件直接连接进入可执行程序
- 动态连接: 在程序启动后才动态加载运行
以上内容参考狄泰软件学院系列课程,请你们保护原创!code