C++中静态库与动态库的使用示例

 更新时间:2023年09月26日 09:44:32   作者:pSomng  
在C/C++中使用库的技术,库主要分为两种类型:静态库和动态库,本文主要介绍了C++中静态库与动态库的使用示例,具有一定的参考价值,感兴趣的可以了解一下

单独提这个,我想我们在coding过程中,可能也会知道一两个词,如 标准库、xx库等。库作为一组已编写好、组织好的、可复用的资源接口,可以被用于其他程序。很不夸张地说,很多程序都需要依赖一些底层依赖库,从而支撑它们完成一些基础工作。

库主要分为两种类型:静态库(static library)动态库(shared library)

静态库

静态库是一个在链接过程中采用静态链接方式链接进可执行文件中的库文件,在静态链接方式中,可执行文件会拷贝静态库中导出的接口并使其成为它的一部分。在Windows系统中它主要是以.lib为后缀,而在Linux系统中,主要以.a为后缀。

构建静态库

项目结构为:

.
├── CMakeLists.txt
├── library.h
├── library.cpp

CMakeLists.txt中的内容为:

cmake_minimum_required(VERSION 3.26)
project(library)
set(CMAKE_CXX_STANDARD 11)
add_library(library STATIC library.cpp)

library.h的内容为:

#ifndef HELLO_LIB_LIBRARY_H
#define HELLO_LIB_LIBRARY_H
#include <string>
class   Test {
public:
    explicit Test(std::string str);
    std::string  getStr() ;
    static int getNum() ;
private:
    std::string str_;
    static int num; // count value
};
void  print();
#endif //HELLO_LIB_LIBRARY_H

library.cpp的内容为:

#include "library.h"
#include <iostream>
int Test::num = 0; // init
Test::Test(std::string str):str_(std::move(str)) {}
std::string Test::getStr()  {
     ++num;
    return str_;
}
 int Test::getNum(){
     return  num;
 }

采用cmake进行构建,即可生成对应的静态库文件,在Window环境下将会生成library.lib,而在Linux环境下将会生成liblibrary.a

随后可以在另一个项目中使用它,项目结构为:

.
├── build
├── CMakeLists.txt
├── include
│   └── library.h
├── lib
│   └── library.lib
└── src
    └── main.cc

CmakeLists.txt的内容为:

cmake_minimum_required(VERSION 3.10)
project(lib_test)
set(CMAKE_CXX_STANDARD 11)
include_directories(include)
# 增加链接库的搜索路径
link_directories(lib)
# 链接 library库
link_libraries(library)
add_executable(${PROJECT_NAME} src/main.cc)

而随后就可以在main.cc中使用它们了:

#include<iostream>
#include"library.h"
int main()
{
    Test test("Hello");
    std::cout << test.getStr();
    std::cout << Test::getNum();
    return 0;
}

动态库

动态库也叫做共享库,在编译时并不会将所导出的接口拷贝到可执行文件中,而是在运行时才会被程序所引用。在Windows系统中它主要是以.dll为后缀,而在Linux系统中,主要以.so为后缀。需要特别注意的是,在MSVC编译器中,Windows环境下不仅生成dll后缀文件,还会生成.lib文件,该文件此刻的作用是作为一个导入库

构建动态库

项目结构大体上和上述提到的构建的静态库一致,但还需要修改一下CMakeLists以及library.h(针对MSVC编译器,Linux环境、MinGW-gcc不用管)。

library.h文件:

#ifndef HELLO_LIB_LIBRARY_H
#define HELLO_LIB_LIBRARY_H
#ifndef EXPORTTING
#define DECLSPEC __declspec(dllimport)
#else
#define DECLSPEC __declspec(dllexport)
#endif // EXPORTTING
#include <string>
class DECLSPEC  Test {
public:
    explicit Test(std::string str);
    std::string  getStr() ;
    static int getNum() ;
private:
    std::string str_;
    static int num; // count value
};
void DECLSPEC  print();
#endif //HELLO_LIB_LIBRARY_H

需要额外的添加__declspec(dllexport)指示这个类/函数是一个可导出类或函数,以便在dll中导出它的接口同时在lib中有对应的符号信息(只有添加了它,MSVC才会生成必需的.lib导入库)。同时在使用这个库的项目中引用相关的头文件也需要添加__declspec(dllimport)来导入所需的数据(没有这个扩展的话,在一些场景时会出现无法解析符号的错误,比如静态数据的导出等),所以为了方便使用同一个头文件,在这里采用一个宏来标识这两者的切换时刻。(构建库时导出(__declspec(dllexport)),使用库时导入(__declspec(dllimport)))

修改CMakeLists文件:

cmake_minimum_required(VERSION 3.26)
project(library)
set(CMAKE_CXX_STANDARD 11)
# SHARED 共享库
add_library(library SHARED library.cpp)
# 加入预定义宏 EXPORTTING
add_definitions(-DEXPORTTING )

在对应环境下采用Cmake工具 构建即可得到对应环境下的动态库文件,比如Windows环境下会生成.lib文件和.dll文件,.lib直接和静态库的配置方式一样,在CMakeLists中修改即可,而将.dll文件直接放置在可执行文件同一路径下,即可隐式链接、调用。而在Linux环境中,只会生成一个.so文件,其在其他项目的cmake使用配置与静态库配置一致。

前面提到的cmake工具构建,构建涉及的命令可以归纳为以下步骤:

# 在项目根目录下执行
# 创建build目录 并进行构建
cmake -Bbuild
# 执行 make 即可完成构建
# 方式一
cd build 
make
# 方式二 build 是构建目录 lib_test 是构建目标名
cmake --build build --target lib_test -j 8

它们的不同

  • 链接时刻不同:静态库会在编译期完成拷贝与链接,而动态库会在运行时按需载入。
  • 可执行文件大小不同:静态库需要整体进行拷贝成为可执行文件的一部分,而动态库无需拷贝多次(拷贝一次,而后其他程序进行共享),故对于同一个库,采用动态链接会使得体积相比静态库更小。
  • 执行速度不同:静态库在编译期间已经完成链接,而动态库则会有额外的动态载入开销,所以相对来说,静态链接库更快。
  • 库更新的影响不同:静态库因为会成为可执行文件的一部分,所以其更新的时候会导致可执行文件也需要重新编译,而动态库只需更新版本即可(接口不变)。

到此这篇关于C++中静态库与动态库的使用示例的文章就介绍到这了,更多相关C++ 静态库与动态库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • 如何实现一定概率选中某一个字母

    如何实现一定概率选中某一个字母

    本篇文章是对如何实现一定概率选中某一个字母的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C/C++ INI文件操作实现代码

    C/C++ INI文件操作实现代码

    本文章主要为分享C/C++ INI文件操作实现代码,增加注释和修复了一些问题。这里给出完整的实现文件,在需要的地方包含该头文件就好了
    2020-02-02
  • opencv摄像头捕获识别颜色

    opencv摄像头捕获识别颜色

    这篇文章主要介绍了opencv摄像头捕获识别颜色,用opencv通过摄像头捕获识别颜色,红色蓝色等,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Pthread并发编程之线程基本元素和状态的剖析

    Pthread并发编程之线程基本元素和状态的剖析

    本篇文章主要给大家介绍pthread并发编程当中关于线程的基础概念,并且深入剖析进程的相关属性和设置,以及线程在内存当中的布局形式,帮助大家深刻理解线程
    2022-11-11
  • C语言超详细讲解顺序表的各种操作

    C语言超详细讲解顺序表的各种操作

    大家好,今天给大家带来的是顺序表,我觉得顺序表还是有比较难理解的地方的,于是我就把这一块的内容全部整理到了一起,希望能够给刚刚进行学习数据结构的人带来一些帮助,或者是已经学过这块的朋友们带来更深的理解,我们现在就开始吧
    2022-05-05
  • 使用udp发送>=128K的消息会报ENOBUFS的错误的解决方法

    使用udp发送>=128K的消息会报ENOBUFS的错误的解决方法

    在项目中选择了unix域的数据报套接口。在使用过程中碰到了如下,问题:发送<128K的消息时,客户、进程可以正常收发消息;发送>=128K的消息时,发送端(sendto)返回ENOBUFS的错误。下面小编来详细说下
    2019-05-05
  • C语言实现简单的扫雷游戏操作

    C语言实现简单的扫雷游戏操作

    这篇文章主要为大家详细介绍了C语言实现简单的扫雷游戏操作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • opencv实现角点检测

    opencv实现角点检测

    这篇文章主要为大家详细介绍了opencv实现角点检测,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言数据结构 快速排序实例详解

    C语言数据结构 快速排序实例详解

    这篇文章主要介绍了C语言数据结构 快速排序实例详解的相关资料,快速排序采用分治的思想,两边数据进行排序,需要的朋友可以参考下
    2017-08-08
  • C++实现打印两个有序链表公共部分的方法

    C++实现打印两个有序链表公共部分的方法

    这篇文章主要介绍了C++实现打印两个有序链表公共部分的方法,涉及C++针对有序链表的简单遍历、比较相关操作技巧,需要的朋友可以参考下
    2017-05-05

最新评论