1(1)库文件:静态库文件 和 共享库文件
(2)比较
a.静态库文件:
使用静态库文件时,直接把代码/指令复制到目标文件中
目标文件会显得比较庞大,修改和维护都不方便
可以脱离静态库文件,效率比较高
b.共享库文件:
使用共享库时,将代码/指令所对应的地址复制到目标文件
目标文件会比较小,修改和维护比较方便
不可以脱离共享库文件,效率比较低
(3)基本命令
ldd a.out => 查看文件a.out所依赖的库文件
gcc/cc -static xxx.c => 要求按照静态库方式编译链接,得到的可执行文件会比较大
2 静态库文件的生成和使用
(1)静态库文件的生成步骤
a.编写源代码xxx.c,如:vi adder.c
b.只编译不链接生成.o的目标文件
gcc/cc -c adder.c
c.使用命令ar -r/*插入*/ lib库名.a xxx.o 生成静态库
ar -r libadder.a adder.o
注意:
a.lib库名.a 叫做静态库文件名,与库名不同,注意区分
b.静态库文件的命名规则一般为lib开头,.a为后缀,中间的库名自定义即可
(2)静态库文件的使用步骤
a.编写源程序xxx.c,如:vi main.c
b.只编译不链接,生成目标文件.o
如: cc -c main.c
c.连接目标文件和静态库文件
1)直接连接
cc main.o libadder.a
2)通过选项进行连接(掌握)
cc main.o -l 库名 -L 库文件所在的路径
cc main.o -l adder -L .
3)配置环境变量LIBARARY_PATH
export LIBRARY_PATH=$LIBRARY_PATH:.
cc main.o -l adder
3.3 共享库的生成和使用步骤
(1)共享库的生成步骤
a.编写源程序xxx.c,如 vi adder.c
b.只编译不链接生成.o目标文件
gcc/cc -c -fpic/*小模式*/ adder.c
c.使用编译选项生成共享库文件
gcc/cc -shared/*共享*/ adder.o -o lib库名.so
(2)共享库的使用步骤
a.编写测试程序xxx.c,如 vi main.c
b.只编译不链接生成.o目标文件
如: cc -c main.c
c.连接测试文件和共享库文件
1)直接连接
cc main.o libadder.so
2)使用编译选项进行连接(掌握)
cc main.o -l adder -L .
3)配置环境变量LIBRARY_PATH
export LIBRARY_PATH=$LIBRARY_PATH:.
cc main.o -l adder
注意:
对于共享库文件的使用来说,要求配置LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
共享库的动态加载
(1)dlopen函数
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
第一个参数:字符串形式的文件名
第二个参数:加载标志
RTLD_LAZY - 延迟加载
RTLD_NOW - 立即加载
返回值:返回共享库文件的句柄/地址
函数功能:打开和加载共享库文件,根据返回值来可以
操作该共享库文件
(2)dlerror函数
char *dlerror(void);
函数功能:
主要用于获取dlopen()/dlsym()/dlclose()/函数调用期间发生的最新错误信息,
通过返回值返回,返回NULL则没有错误
(3)dlsym函数
void *dlsym(void *handle, const char *symbol);
第一个参数:dlopen函数的返回值
第二个参数:标识,一般用于查找具体的函数名
返回值:返回标识在内存中的地址
函数功能:
根据handle在对应的共享库中查找名字为symbol标识的地址
(4)dlclose函数
int dlclose(void *handle);
函数功能:
表示关闭handle所对应的共享库文件
注意:
连接的时候需要指定选项: -ldl
动态库使用示例:
//加法计算的头文件 #ifndef ADDER_H #define ADDER_H //计算两个int类型参数的和 int add_int(int ia,int ib); //计算两个double类型参数的和 double add_double(double da,double db); #endif
//加法计算的源文件 #include "adder.h" //#include "../adder.h" //计算两个int类型参数的和 int add_int(int ia,int ib) { return ia + ib; } //计算两个double类型参数的和 double add_double(double da,double db) { return da + db; }
//共享库的动态加载 #include <stdio.h> #include <dlfcn.h> int main(void) { //1.打开和加载共享库文件 void* handler = dlopen("./shared/libadder.so",RTLD_NOW); //2.判断是否出错 char* error = dlerror(); if(error != NULL) { printf("加载共享库文件失败\n"); return -1; } //3.寻找共享库中指定的标识 int (*add_pint)(int ia,int ib); add_pint = dlsym(handler,"add_int"); //4.判断是否出错 error = dlerror(); if(error != NULL) { printf("获取标识失败\n"); return -1; } //5.使用标识进行处理 printf("计算的结果是:%d\n",add_pint(10,20));//30 //6.关闭共享库文件 dlclose(handler); return 0; }