库是旨在被许多程序重用的代码包。通常,C++ 库包含两部分
- 一个头文件,定义了库向使用它的程序公开(提供)的功能。
- 一个预编译的二进制文件,包含该功能的实现,已预编译成机器语言。
一些库可能被拆分为多个文件和/或有多个头文件。
库预编译有几个原因。首先,由于库很少更改,因此无需经常重新编译。每次编写使用它们的程序时都重新编译库会浪费时间。其次,由于预编译的对象是机器语言,因此可以防止人们访问或更改源代码,这对于出于知识产权原因不想公开源代码的企业或个人来说很重要。
库有两种类型:静态库和动态库。
静态库(也称为归档)由直接编译并链接到程序中的例程组成。当您编译使用静态库的程序时,您的程序使用的静态库的所有功能都成为可执行文件的一部分。在 Windows 上,静态库通常具有 .lib 扩展名,而在 Linux 上,静态库通常具有 .a(归档)扩展名。静态库的一个优点是,您只需分发可执行文件即可让用户运行您的程序。由于库成为程序的一部分,这确保了始终使用正确版本的库。此外,由于静态库成为程序的一部分,您可以像使用为自己的程序编写的功能一样使用它们。缺点是,由于库的副本成为使用它的每个可执行文件的一部分,这会造成大量空间浪费。静态库也无法轻松升级——要更新库,需要替换整个可执行文件。
动态库(也称为共享库)由在运行时加载到应用程序中的例程组成。当您编译使用动态库的程序时,库不会成为可执行文件的一部分——它仍然是一个独立的单元。在 Windows 上,动态库通常具有 .dll(动态链接库)扩展名,而在 Linux 上,动态库通常具有 .so(共享对象)扩展名。动态库的一个优点是许多程序可以共享一个副本,这节省了空间。也许更大的优点是动态库可以升级到新版本,而无需替换使用它的所有可执行文件。
由于动态库没有链接到您的程序中,因此使用动态库的程序必须显式加载并与动态库交互。这种机制可能令人困惑,并且使与动态库的交互变得笨拙。为了使动态库更易于使用,可以使用导入库。
导入库是一种自动加载和使用动态库的库。在 Windows 上,这通常通过一个与动态库 (.dll) 同名的小型静态库 (.lib) 来完成。静态库在编译时链接到程序中,然后动态库的功能可以有效地用作静态库。在 Linux 上,共享对象 (.so) 文件既可以作为动态库也可以作为导入库。大多数链接器在创建动态库时都可以为动态库构建导入库。
安装和使用库
现在您了解了不同类型的库,接下来我们讨论如何在程序中实际使用库。在 C++ 中安装库通常涉及 4 个步骤
- 获取库。最好的选择是下载适用于您的操作系统的预编译包(如果存在),这样您就不必自己编译库。如果您的操作系统没有提供,您将不得不下载仅源代码包并自行编译(这超出了本课程的范围)。在 Windows 上,库通常以 .zip 文件的形式分发。在 Linux 上,库通常以包的形式分发(例如 .RPM)。您的包管理器可能已经列出了一些更流行的库(例如 SDL),以便于安装,因此请先在那里检查。
- 安装库。在 Linux 上,这通常涉及调用包管理器并让它完成所有工作。在 Windows 上,这通常涉及将库解压缩到您选择的目录中。我们建议将所有库保存在一个位置,以便于访问。例如,使用名为 C:\Libs 的目录,并将每个库放在其自己的子目录中。
- 确保编译器知道在哪里查找库的头文件。在 Windows 上,这通常是您安装库文件的目录的 include 子目录(例如,如果您将库安装到 C:\libs\SDL-1.2.11,则头文件可能在 C:\libs\SDL-1.2.11\include 中)。在 Linux 上,头文件通常安装到 /usr/include,这应该已经是您的包含文件搜索路径的一部分。但是,如果文件安装在其他地方,您将不得不告诉编译器在哪里找到它们。
- 告诉链接器在哪里查找库文件。与步骤 3 一样,这通常涉及将目录添加到链接器查找库的位置列表中。在 Windows 上,这通常是您安装库文件的目录的 /lib 子目录。在 Linux 上,库通常安装到 /usr/lib,这应该已经是您的库搜索路径的一部分。
一旦库安装完成并且 IDE 知道在哪里查找它,通常需要为每个想要使用该库的项目执行以下 3 个步骤
- 如果使用静态库或导入库,请告诉链接器要链接哪些库文件。
- 在您的程序中 #include 库的头文件。这会告诉编译器库提供的所有功能,以便您的程序能够正确编译。
- 如果使用动态库,请确保程序知道在哪里找到它们。在 Linux 下,库通常安装到 /usr/lib,它在
LD_LIBRARY_PATH
环境变量中的路径之后位于默认搜索路径中。在 Windows 上,默认搜索路径包括程序运行的目录、通过调用 SetDllDirectory() 设置的目录、Windows、System 和 System32 目录以及 PATH 环境变量中的目录。使用 .dll 最简单的方法是将 .dll 复制到可执行文件的位置。由于您通常会随可执行文件一起分发 .dll,因此无论如何将它们放在一起是有意义的。
步骤 3-5 涉及配置您的 IDE——幸运的是,几乎所有 IDE 在执行这些操作时的工作方式都相同。不幸的是,由于每个 IDE 都有不同的界面,这个过程中最困难的部分就是简单地找到执行每个步骤的正确位置。因此,在本节的接下来的几课中,我们将介绍如何为 Visual Studio 和 Code::Blocks 执行所有这些步骤。如果您正在使用其他 IDE,请阅读两者——当您完成时,您应该有足够的信息,通过一点点搜索,在您自己的 IDE 中做同样的事情。