• 静态库与动态库区别


    什么是库

    库是写好的,成熟的,可以复用的代码,一般程序运行都需要依赖许多底层库文件。

    本质上来说库是一种可可执行代码的二进制形式,可以被操作系统载入内存执行,库有两种:静态库(.a、.lib)和动态库(.so、.dll)。

    静态、动态是指链接,将一个程序编译成可执行程序步骤如下:

    程序编译过程

    静态库

    所谓静态库,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,对应的链接方式成为静态链接。

    静态库与汇编生成的目标文件一起链接成为可执行文件,那么可以得出,静态库的格式跟.o文件格式相似,其实一个静态库可以简单看成是一组目标文件(.o/.ojb文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。

    • 优点
      • 程序在运行时与函数库就没有关系,移植方便
    • 缺点
      • 浪费空间和资源,所有相关的目标文件与牵涉的函数库被链接合成一个可执行文件

    Linux下创建与使用静态库

    Linux下静态库命名规则

    必须是lib{your_library_name}.a:lib为前缀,中间是静态库名,扩展名为.a

    创建静态库(.a)

    下面以一个简单四则运算C++类为例,将其编译为静态库给他人用。

    头文件

    class StaticMath {
      public:    
        static double add(double a, double b);
        static double sub(double a, double b);
        static double mul(double a, double b);
        static double div(double a, double b);
        void print();
    };
    

    实现

    #include "StaticMath.h"
    #include <iostream>
    
    double StaticMath::add(double a, double b) {
      return a + b;
    }
    
    double StaticMath::sub(double a, double b) {
      return a - b;
    }
    
    double StaticMath::mul(double a, double b) {
      return a * b;
    }
    
    double StaticMath::div(double a, double b) {
      return a / b;
    }
    
    void StaticMath::print() {
      std::cout << "Static Math Library" << std::endl;
    }
    

    Linux通过ar工具,Windows下vs使用lib.exe,将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和检索。一般创建静态库的步骤如下:

    创建静态库过程
    • 将代码文件编译为目标文件.o(StaticMath.o)

    g++ -c StaticMath.cpp

    • 通过ar命令将目标文件打包为.a静态文件

    ar -crv libstaticmath.a StaticMath.o

    生成静态库libstaticmath.a

    使用静态库

    • 编写测试代码
    #include "StaticMath.h"
    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char *argv[]) {
      double a = 10;
      double b = 2;
      cout << "a + b = " << StaticMath::add(a, b) << endl;
      cout << "a - b = " << StaticMath::sub(a, b) << endl;
      cout << "a * b = " << StaticMath::mul(a, b) << endl;
      cout << "a / b = " << StaticMath::div(a, b) << endl;
      StaticMath sm;
      sm.print();  
      return 0;
    }
    

    Linux环境下使用静态库,只需要在编译的时候,指定静态库搜索路径(-L选项)和指定库名
    (-l选项)

    # 编译
    g++ -o staticmatch StaticMathTest.cpp -L/home/username/googletest/mybuild/mytest  -lstaticmath
    # 执行
    ./staticmatch
    

    动态库

    为什么需要动态库?

    • 静态库会造成空间浪费,如下图:

    • 静态库对程序更新、部署和发布会带来麻烦,如果静态库更新,则所有使用它的应用程序都需要重新编译、发布给用户(一个小的改动,可能导致整个程序重新下载)。

    动态库优点

    • 可以实现进程之间资源共享(因此动态库也称为共享库),如下图:

    • 使程序升级变得简单

    Linux下创建与使用动态库

    Linux下动态库命名规则
    命名形式为libxxx.so,前缀是lib,后缀名为“.so”

    创建静态库(.so)

    类似四则运算代码

    头文件

    class DynamicMath {
      public:       
        static double add(double a, double b);
        static double sub(double a, double b);
        static double mul(double a, double b);
        static double div(double a, double b);
        void print();
    };
    

    实现

    #include "DynamicMath.h"
    #include <iostream>
    
    double DynamicMath::add(double a, double b) {
      return a + b;
    }
    
    double DynamicMath::sub(double a, double b) {
      return a - b;
    }
    
    double DynamicMath::mul(double a, double b) {
      return a * b;
    }
    
    double DynamicMath::div(double a, double b) {
      return a / b;
    }
    
    void DynamicMath::print() {
      std::cout << "DynamicMath Math Library" << std::endl;
    }
    

    与静态库不同,创建动态库不需要打包工具(ar,lib.exe),直接使用编译器即可创建动态库。

    • 生成目标文件,加编译选项-fpic

    g++ -fPIC -c DynamicMath.cpp

    • 生成动态库,加编译选项-shared

    g++ -shared -o libdynmath.so DynamicMath.o

    上面两个命令也可以合并为一个

    g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp

    使用静态库

    • 编写测试代码
    #include "DynamicMath.h"
    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char *argv[]) {
      double a = 10;
      double b = 2;
      cout << "a + b = " << DynamicMath::add(a, b) << endl;
      cout << "a - b = " << DynamicMath::sub(a, b) << endl;
      cout << "a * b = " << DynamicMath::mul(a, b) << endl;
      cout << "a / b = " << DynamicMath::div(a, b) << endl;
      DynamicMath dyn;
      dyn.print();  
      return 0;
    }
    

    由于动态库是在程序运行时进行链接,所以在程序运行时需要让系统能够找到动态库,系统一般会依次搜索:环境变量LD_LIBRARY_PATH、/etc/ld.so.cache文件列表、/lib、/usr/lib目录找到库文件后将其载入内存。因此主要有三种方法来设置动态库路径。

    • 将动态库绝对路径加入环境变量LD_LIBRARY_PATH
    • 将动态库绝对路径加入/etc/ld.so.cache文件中,步骤如下:
      • 编辑/etc/ld.so.conf文件,加入文件所在目录的路径
      • 运行ldconfig,重建/etc/ld.so.cache
    • 将动态库移到/lib或/usr/lib中
    # 编译
    g++ -o dynamicmath DynamicMathTest.cpp -L/home/dgh/googletest/mybuild/mytest -ldynmath
    # 执行
    ./dynamicmath # 需要先设置好动态库路径
    

    参考资料

    C++静态库与动态库

  • 相关阅读:
    Swing中的并发使用SwingWorker线程模式
    使用批处理打二次开发包
    【转】批处理删除SVN文件
    EAS BOS ORMapping的研究
    EAS BOS ORMapping 元数据解析示例
    ORMapping学习
    EAS BOS数据查询默认会查分录的分析
    【Oracle】常用查询
    KDTable公式解析提示信息设置
    【转】Swing多线程编程
  • 原文地址:https://www.cnblogs.com/galaxy-hao/p/13173029.html
Copyright © 2020-2023  润新知