当前位置:网站首页>【genius_platform软件平台开发】第七十四讲:window环境下的静态库和动态库的一些使用方法(VC环境)
【genius_platform软件平台开发】第七十四讲:window环境下的静态库和动态库的一些使用方法(VC环境)
2022-07-31 00:58:00 【隨意的風】
这里写目录标题
1 windows环境下(vs环境)
1.1 静态库
- 一个程序需要经过很多步骤才可以最终形成可执行程序,在其中某一个步骤中执行编译时会生成.obj文件(程序的编译、连接过程这里不做详解,可以自行查阅相关资料),把多个.obj文件归档为一个lib文件,那么这个
xxxx.lib文件就是静态库文件。一般扩展名为(.a或.lib),这类的函数库通常扩展名为libxxx.a或xxx.lib 。这类库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译成的文件会比较大,这类函数库最大的优点就是编译成功的可执行文件可以独立运行,而不再需要向外部要求读取函数库的内容;但是从升级难易度来看明显没有优势,如果函数库更新,需要重新编译。
1.1.1 配置使用方式
1.1.1.2 vs工程属性配置
- 工程中加入某个静态库时,需要
右键工程->属性->链接器->输入->附加依赖项中添加xxxx.lib,在属性页->链接器->常规->附加库目录中添加xxxx.lib的对应目录即可;


1.1.1.2 vs项目直接添加lib文件(有待验证)
- 项目中直接加入xxxx.lib,
项目右键->添加->现有项,选择正确的xxxx.lib
1.1.1.3 代码中指令静态添加lib库
- 可以在头文件或者源文件中添加以下指令
#pragma comment(lib, "##/##xxxx.lib"),可以不填写路径名,在上述路径中配置或者添加到系统环境变量path中,系统会优先查找环境变量path; - 在工程中包含xxxx.h头文件,#include “xxxx.h”,可以在工程中配置或者代码中写全绝对路径、相对路径(相对于工程(即.dsp文件)所在目录的相对路径)也可以。
- 如果头文件比较多,可以在
工程>属性页>c/c++->常规->附加包含目录中填入你的头文件所在目,或者在VC2017里面IDE设置是在视图-〉其他窗口->属性管理器中看到各个版本的.user等配置,每个分支都有一个Microsoft.Cpp.***.user文件,双击Microsoft.Cpp.Win32.user弹出属性页面;

- 双击Debug | Win32下的Microsoft.Cpp.Win32.user,会弹出Microsoft.Cpp.Win32.user的属性页,然后在左边的菜单中选择"VC++目录"

- 选择右边的"包含目录"的编辑选项

- 在弹出的窗口中,选择新行,如图


- 然后添加要设定路径,如"
D:\IncludePath",如图:
- 点击确定,完成添加,最后效果如图

- 设定库目录,如"D:\LibPath",如图:

- 其他的3个分支,也要分别添加引用目录和库目录;
- 保存整个项目。
注意:
- 这个设置是项目无关的,所以如果你把这个设置用的项目删除也不会有影响;
- 上面说的4个分支都要设置,这样在你切换编译的类型和位数时才不会报错;
- 虽然你这里设定了库的目录,但是真正需要引用库时,还需要在上述的
Microsoft.Cpp.Win32.user的属性页的"链接器"->“输入”->"附加依赖项"中添加所需库的名字(操作和添加目录类似,这里不再赘述),假设库名称为opengl32.lib,添加完成如下图所示:
1.1.2 与可执行程序连接
- 当编译可执行程序与静态库链接时,静态库中所包含的所有函数实现代码(二进制)、全局数据等都会被copy到最终的可执行文件中去。缺点: 占用磁盘和内存空间,导致可执行exe程序过大;
- 这种方式会让程序运行起来相对快一些,不需要再去加载任何相关库的东西了,都在可执行文件中了;
- 静态库会被添加到和它链接的每个程序中去,每个程序都会有一份相关的代码, 而且这些程序运行时相互不干扰, 每个进程都会被加载到内存中,无形中又多消耗了更多的内存空间;
1.2 动态库
- 动态函数库的扩展名一般为(.so或.dll),这类函数库通常名为libxxx.so或xxx.dll 。
与静态函数库被整个捕捉到程序中不同,动态函数库在编译的时候,在程序里只有一个“指向”的位置而已,也就是说当可执行文件需要使用到函数库的机制时,程序才会去读取函数库来使用;也就是说可执行文件无法单独运行。这样从产品功能升级角度方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件;
1.2.1 配置使用方式
- 动态链接库一般包括
xxxx.lib(导入库),xxxx.h,xxxx.dll文件,使用动态库有两种情况
1.2.1.1 隐式链接:load-time dynamic linking
- vs工程属性配置,同使用静态库相似,分为三步:引用.lib导入库(此时把Dll和lib 后缀的文件都要放进来),包含头文件(h后缀文件),使用导出函数;
- 此种方法的好处是:可以像使用静态库一样直接调用函数
- 缺点:程序启动时加载所有需要的DLL,延长启动时间,效率低。
- 这种做法成功的原因是:导入库lib中包含了dll文件中导出函数的位置,所以当调用某个函数时,就知道去执行dll中该函数的函数体。
1.2.1.1 动态加载:run-time dynamic linking
- 直接使用
LoadLibrary或LoadLibraryEx加载所需的动态库(并不需要对应的头文件.h,和LIB),然后指定所需的导出函数,效率最高!,但前提需要对DLL库有比较详细的了解。 - 缺点:需要使用
GetProcessAddress()得到函数指针,函数调用相对麻烦。 - 这种做法成功的原因是:通过
LoadLibrary强行将dll文件加载到内存,然后通过GetProcessAddress()函数取得你所要调用的函数的地址,然后通过该地址去执行dll文件中该函数的函数体。
注意
1.2.2 输入库(导入库)
扩展名.lib,目标库的一种特殊形式。输入库不含代码,而是为链接程序提供信息,以便在.exe文件中建立动态链接时要用到的重定位表。
输入库是动态库的辅助库,在vc中隐式导入动态库的时候用到该库,需要在引用该库的文件中包含该库的头文件 ,并让连接程序能找到该输入库的位置(放在同一目录下或在vc中作相应的设置)。
目标库和输入库之用在程序的开发期间,动态库在运行期间使用。
1.2.3 两种lib的不同
- 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。
静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。
动态库一般会有对应的导入库,方便程序静态载入动态链接库(即导入库lib也被链接到exe文件中去),否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。
导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息;相同点:都被链接到exe文件中去。
1.2.4 开源代码发布的惯用方式:
(1). 预编译的开发包:包含一些.dll文件和一些.lib文件。其中这里的.lib就是导入库,而不要错以为是静态库。但是引入方式和静态库一样,要在链接路径上添加找到这些.lib的路径。而.dll则最好放到最后产生的应用程序exe执行文件相同的目录。这样运行时,就会自动调入动态链接库。
(2). 用户自己编译:下载的是源代码,按照readme自己编译。生成很可能也是.dll + .lib(导入库)的库文件
(3). 如果你只有dll,并且你知道dll中函数的函数原型,那么你可以直接在自己程序中使用LoadLibary调入DLL文件,GetProcAddress
1.2.5 一些导入函数的介绍
- LoadLibrary
一般是动态加载DLL时(你并不需要对应的头文件,和LIB),显示加载dll中函数,前提是你自己对dll导出的函数参数很了解.
- #pragma comment
一般是静态加载DLL时(对应的头文件、DLL,和LIB缺一不可,并且生产的EXE没有找到DLL文件就会导致“应用程序初始化失败”)
- #import
导入的dll是com组建的dll,主要用来解析com组建内部结构,便与c++识别调用
边栏推荐
- The level of ShardingSphere depots in actual combat (4)
- XSS related knowledge
- Typescript14 - (type) of the specified parameters and return values alone
- 822. Walk the Grid
- Summary of MySQL database interview questions (2022 latest version)
- [Yugong Series] July 2022 Go Teaching Course 015-Assignment Operators and Relational Operators of Operators
- 822. 走方格
- Artificial Intelligence and Cloud Security
- Basic Parameters of RF Devices 2
- Installation problem corresponding to tensorflow and GPU version
猜你喜欢

响应式布局与px/em/rem的比对

Unity2D horizontal version game tutorial 4 - item collection and physical materials

WEB Security Basics - - - Vulnerability Scanner

typescript10-常用基础类型

Dispatch Center xxl-Job

typescript10-commonly used basic types

API 网关 APISIX 在Google Cloud T2A 和 T2D 的性能测试

无线模块的参数介绍和选型要点

Error in go mode tidy go warning “all” matched no packages

How to Add a Navigation Menu on Your WordPress Site
随机推荐
WEB Security Basics - - - Vulnerability Scanner
ShardingSphere之未分片表配置实战(六)
Consistency and Consensus of Distributed Systems (1) - Overview
JS逆向之浏览器补环境(一)
ShardingSphere之读写分离(八)
华为“天才少年”稚晖君又出新作,从零开始造“客制化”智能键盘
DOM系列之scroll系列
typescript16-void
"Actual Combat" based on part-of-speech extraction in the field of e-commerce and its decision tree model modeling
ELK deployment script---pro test available
[Yugong Series] July 2022 Go Teaching Course 016-Logical Operators and Other Operators of Operators
In Google Cloud API gateway APISIX T2A and T2D performance test
MySQL notes under
Basic usage of async functions and await expressions in ES6
使用docker安装mysql
What is Promise?What is the principle of Promise?How to use Promises?
XSS related knowledge
Summary of MySQL database interview questions (2022 latest version)
小黑leetcode之旅:117. 填充每个节点的下一个右侧节点指针 II
调度中心xxl-Job