本文对动态链接库的链接和运行进行一个总结,为什么要分开说呢?因为链接通过生成可执行文件并不代表运行时能找到依赖的动态库。这与静态库是不一样的,因为静态库在编译完成后会库会编译到可执行程序中,但是动态链接库则不然,仅仅只是在可执行文件中打了一个标记,标识依赖哪个动态库文件。如何编译动态库或者如何编译静态库,这个很简单,在创建工程的时候进行就可以了,本文重点讲述动态库编译完成后如何链接到可执行程序中。下面将区分window平台和linux平台进行介绍。
在编译阶段,如何保证编译可执行程序依赖动态链接库编译通过呢?需要在编译选项中添加-L选项指定依赖动态链接库的路径。
这里要建立一个认识:如果一个可执行程序依赖另一个动态链接库,那么可执行程序能够正确的编译链接出来,并不代表该可执行之程序可以正常运行,因为在编译链接阶段能够成功仅仅代表可知形程序中依赖的动态链接库中的符号能够在动态链接库中找到,更直白一点的理解就是将可执行程序中的依赖的动态链接库的符号对应的位置打上动态链接库的标签,告知程序依赖哪个动态链接库。那为什么可执行程序可能不会正常运行呢?因为可执行程序仅仅在程序中标记了依赖哪个动态链接库,但是并未标明该动态链接库在哪里,所以运行的时候有可能找不到依赖的动态链接库,这就是可能运行出错的原因。解决问题的方法大致有两种
- 在编译阶段通过添加编译选项指定动态链接库的位置,例如-Wl -rpath
- 可执行程序搜索动态链接的路径会有几种默认的顺序,在任意一种方法中加入依赖的动态库均可。例如Linux系统下添加依赖库可以选择LD_LIBRARY_PATH环境变量来完成。
Windows VS Studio 2017
通过vs studio编译的动态库为dll后缀,在vs studio去哪里搜索依赖的动态库呢?下面给出几个路径:
- 应用程序所在目录,即exe后缀的文件所在路径
- 系统环境变量path,但是设置系统环境变量会影响所有的工程,还可能会造成符号冲突。
- 设置工程环境变量,该环境变量仅应用于本工程,影响范围,是比较好的方法。设置方法如下图所示:
上面的总结是运行情况下的总结,那么编译过程中如果依赖dll文件,如何保证编译通过呢?
这个问题在gcc编译器下不存在问题,但是是用使用vs studio则不容易理解,因为生成一个dll会生成三个文件,test.lib test.dll test.h,为了编译通过需要在附近库目录中包含test.lib,在头文件中包含test.h应该就可以编过了。
补充:
使用vs studio 2017测试,下面将测试过程列出:
- 创建一个dll工程,需要注意的是一定在要在希望在别的工程调用的函数前面使用_declspec(export) ,只有使用这个符号才可以生成对应的dll和lib文件;如果不使用这个符号,那么将只会生成dll文件(这种情况下,动态链接库文件将无法被隐式加载,只能显式的调用加载dll接口加载),所以我们如果隐式的声明代码的话,一定要使用_declsepc(export)修饰。另外就是这个修饰符_declspec(export)只能放在源文件中修饰函数定义,用这个符号去修饰头文件中的函数声明是没有效果的。创建完成后输出对应的lib文件和dll文件。
//add.h
int add(int a,int b);
//add.cpp
_declspec(export) int add(int a, int b)
{return a+b;
}
- 创建一个win32控制台应用程序,在工程目录中创建一个目录,将上一个目录中生成中lib文加入到该目录,将依赖的头文件加入到工程中,通过属性->链接器->常规->附加库目录,添加lib文件所在目录。然后再次属性->链接器->常规->附加依赖项 添加依赖的lib名称(注意包含后缀),再次编译通过。
- 直接运行第二步的程序,程序报错,提示缺少dll。如下所示:
总结:上述测试说明了在window下依赖动态链接库的情况下的编译过程与dll无关,仅与lib和头文件有关。
但是运行时需要将dll文件放到指定路径中才可以,因为实际运行时是实际加载对应的符号的,如果找不到该dll文件,则无法将生效。
Linux gcc
在gcc编译器编译过程中依赖的动态链接库文件,路径可以通过-L -l 设置依赖的动态库。
在运行过程中so搜索路径也有好几种:
- 程序编译时用户指定的-Wl -rpath指定的搜索路径
- 环境变量LD_LIBRARY_PATH指定的路径
- /etc/ld.so.conf或/etc/ld.so.conf.d指定的路径
- /lib路径或者/usr/lib路径
参考链接:动态库.lib与.dll关系、visual studio工程库路径配置浅析_动态库为什么会有lib和dll_Coding-Prince的博客-CSDN博客
vs 设置dll依赖库引用路径_vs2019设置dll路径_沐大人的博客-CSDN博客