你的位置:首页 > 操作系统

[操作系统]c的静态库和动态库


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;}