• 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("加载共享库文件失败
    ");
            return -1;
        }
        //3.寻找共享库中指定的标识
        int (*add_pint)(int ia,int ib);
        add_pint = dlsym(handler,"add_int");
        //4.判断是否出错
        error = dlerror();
        if(error != NULL)
        {
            printf("获取标识失败
    ");
            return -1;
        }
        //5.使用标识进行处理
        printf("计算的结果是:%d
    ",add_pint(10,20));//30
        //6.关闭共享库文件
        dlclose(handler);
        return 0;
    }
  • 相关阅读:
    【YbtOJ#20068】连通子图
    【YbtOJ#20067】糖果分配
    【GMOJ6801】模拟patrick
    【GMOJ6800】模拟spongebob
    【洛谷P4449】于神之怒加强版
    【洛谷P3601】签到题
    【洛谷P2408】不同子串个数
    【洛谷P3809】【模板】后缀排序
    【JZOJ1753】锻炼身体
    【GMOJ1164】求和
  • 原文地址:https://www.cnblogs.com/csun/p/5526043.html
Copyright © 2020-2023  润新知