c的静态库和动态库

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于c的静态库和动态库的主要内容,如果未能解决你的问题,请参考以下文章

CGO静态库和动态库

关于动态库和静态库的问题。

Linux下的静态库和动态库

c的静态库和动态库

C语言 | 什么是静态链接库和动态链接库?

C语言里面的动态库和静态库