静态链接库与动态链接库的区别及Windows下的使用

前言

在使用链接库之前,如果我们想要使用其它第三方库的话,常用的方式就是通过在程序中引入相关头文件,并且在编译时指定依赖的源文件,从而编译得到可执行程序。

注意1:g++编译时,通过“-I”参数指定头文件目录时要具体的目录,不能是上层目录,然后让程序自己递归到子目录寻找。

注意2:引入头文件后,需要解决cpp文件的依赖问题,不然会报错:undefined reference。

1. 链接库

因为我们写的程序可能需要依赖一些第三方库,而第三方为了我们方便使用以及一定程度上的屏蔽源码实现,会将源代码转换成库文件,有动态链接库和静态链接库两种。

2. 静态链接库和动态链接库

2.1 静态链接库

2.1.1 Windows下静态链接库文件的后缀为 .lib,Linux下后缀为 .a。

2.1.2 直接将第三方函数链接到目标程序中,运行时不再需要库文件,目标程序可直接执行。

2.1.3 当静态库文件发生变化时,目标程序需要重新编译。

2.1.4 浪费空间,当多个程序使用同一个静态链接库,系统中会存在多个副本。

2.1.5 适用于小型应用开发。

2.2 动态链接库

2.2.1 Windows下动态链接库文件的后缀为 .dll,Linux下后缀为 .so。

2.2.2 编译时,在目标程序中使用第三方函数处做了标记;当程序运行时,才自动加载动态链接库至内存。

2.2.3 方便升级,动态链接库文件变化时无需重新编译目标程序,直接替换动态库文件即可。

2.2.4 节省空间,因为动态库只需一份便可供多个进程使用.

2.2.5 适用于大型应用开发。

3. 静态链接库和动态链接库的生成与使用

3.1 静态链接库的生成

在同一个目录下创建add.cpp和add.h文件,其中add.h文件是一个加法函数的声明,而cpp文件时具体实现,具体如下。注意,在生成静态/动态链接库文件时,Windows下源文件中依赖的非系统头文件引入时使用括号会报错,需要使用引号

// add.h

int sum(int num1, int num2);
// #include  生成库文件时会报错
#include "add.h"

int sum(int num1, int num2)
{
    return num1 + num2;
}

然后,在命令行中进入文件所在目录,执行“g++ -c add.cpp”指令先得到add.o的目标文件,然后执行"ar rcs libadd.lib add.o"指令得到静态链接库libadd.lib文件。

3.2 动态链接库的生成

以add.cpp和add.h为例,在命令行中进入文件所在目录,执行“g++ -fpic -shared add.cpp -o libadd.dll”指令即可得到动态链接库libadd.dll文件。

3.3 静态/动态链接库的使用

在gcc/g++编译目标程序时,通过“-L”指定静态/动态链接库的目录,“-l”指定静态/动态链接库文件(Windows不需要加后缀,加了反而找不到;linux下前缀和后缀都不需要)。并且,由于linux下gcc/g++默认是使用动态链接库(Windows下默认使用静态链接库),所以使用静态链接库时需要加上“-static”参数。同时,需要将编译的目标源文件放在静态链接库信息之前,否则链接错误。此外,虽然使用了静态/动态链接库文件,但仍然需要在目标程序中引入相应的头文件,或者进行相应的声明,否则不知道第三方信息。最终,使用静态链接库和动态链接库编译目标程序的指令如下。

// 使用静态链接库
g++ -static main.cpp -L 链接库/的/路径 -l libadd -o main.exe
// 当静态链接库和目标程序在同一目录,可使用如下指令
// g++ -static main.cpp libadd.lib -o main.exe


// 使用动态链接库
g++ main.cpp -L 链接库/的/路径 -l libadd -o main.exe

3.4 程序运行

静态链接后,可执行程序可以移动至任何地方独立运行;而动态链接后,可执行程序运行需要找得到动态链接库文件,否则报错:由于找不到libadd.dll,无法继续执行代码,重新安装程序可能会解决此问题

Windows动态链接库的查找路径顺序:①当前目录;②C:\\Windows\\system32;③C:\\Windows;④Path环境变量的目录。

Linux动态链接库的查找路径顺序:①LD_LIBRARY_PATH环境变量;②/etc/ld.so.conf文件,然后执行ldconfig指令;③默认的/lib和/usr/lib目录

你可能感兴趣的:(C++,链接库)