.lib .dll文件都是程序可直接引用的文件,前者就是所谓的库文件,后者是动态链接库(Dynamic Link Library)也是一个库文件。而.pdb则可以理解为符号表文件。DLL(Dynamic Link Library)文件为动态链接库文件,又称为“应用程序扩展”,是一种软件文件类型。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即dll文件,放置于系统中。

关于lib和dll的区别

(1)lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
(2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
(3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。

需要的文件

静态链接库(Static Link Library)使用lib需注意两个文件:

  1. h头文件,包含lib中说明输出的类或符号原型或数据结构。应用程序调用lib时,需要将该文件包含入应用程序的源文件中。
  2. LIB文件,这种 lib 中有函数的实现代码,它是将 lib 中的代码加入目标模块(.exe 或者 .dll)文件中,所以链接好了之后,lib 文件就没有用了。这种 lib文件实际上是任意个 obj 文件的集合。obj 文件则是 cpp 文件编译生成的,如果有多个cpp 文件则会编译生成多个 obj 文件,从而生成的 lib 文件中也包含了多个 obj。

动态链接库(Dynamic Link Library)的导入库(Import Library)使用dll需注意三个文件:

  1. h头文件,包含dll中说明输出的类或符号原型或数据结构的.h文件。应用程序调用dll时,需要将该文件包含入应用程序的源文件中。
  2. LIB文件,是dll在编译、链接成功之后生成的文件,作用是当其他应用程序调用dll时,需要将该文件引入应用 程序,否则产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。
  3. dll文件,真正的可执行文件,开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,并不需要.lib文件和.h头文件。

这种 lib 是和 dll 配合使用的,里面没有代码,代码在 dll 中,这种 lib 是用在静态调用 dll 上的,所以起的作用也是链接作用,链接完成了, lib 也没用了。至于动态调用 dll 的话,根本用不上 lib 文件。目标模块(exe 或者 dll)文件生成之后,就用不着 lib 文件了。

引入加载文件

加载lib/头文件(若不添加,连接报错:无法解析的外部符号)

静态链接只需要lib文件,当然头文件也是需要的。这种方式时候lib文件中有两个部分,可以将文件后缀改为rar解压可以看到。第一部分就是和第一种方式中的key,第二部分是.obj文件存储在obj文件夹下,他相当与dll中的机器码,只不过这个机器码是在链接的时候放入程序的,而不是在程序运行时拿进来的。如果这时候我们也有源代码,并且希望IED可以调试源码,这很容易因为如果lib文件生成的时候模式是NDEBUG(好像不是也可以),obj文件夹下是有一个xx.pdb这个pdb文件中的东西会被IED放入程序的pdb中,所以直接指定源代码位置使用就可以了。
1 第一步:项目->属性->C/C++->常规->附加包含目录(浏览.h文件的路径)   添加包含文件
2 第二步:项目->属性->C/C++->链接器->输入->附加依赖项(写入lib的名称) 添加用到的lib (这一步也可以在代码中显示调用 #pragma comment(lib, “***.lib”) )
    项目->属性->C/C++->链接器->常规->附加库目录        添加库文件路径
4 第三步:在要使用cpp文件前加入 #include <gtest/gtest.h>(注意文件的路径)
上述方法,在每次创建工程时都要重新进行设置,而且debug和release都要进行设置,同时注意win32和win64平台。

加载dll(如果不添加,编译链接不报错,运行报错:无法找到***.dll)

这种方式的基本原理是lib文件中包扩了某一段程序(函数)的入口或者说是地址,而他真正的机器码是在dll文件中,IDE链接的时候将.lib文件(程序地址)链接到源代码中,程序运行时到相应位置(环境变量path,当前目录等)寻找dll文件并执行其中的机器码。所以这种引用方式一般需要的文件一般有三个:.h,.lib,.dll,生成的源程序也会比较小,因为他只保存了函数地址,但是这种方式总是会出现找不到xxx.dll这种问题。如果这时候我们还有dll的源代码,并且希望IED可以调试源码,那么就需要.pdb文件了,pdb文件中保存了dll的符号表,所谓符号表可以理解为机器码(这里是dll中的)中插入的key与源代码文件的映射,这样只要指定源码存放的路径,IDE就会自动去找源码。需要注意的是,pdb文件和dll文件是配套的,也就是说一旦dll文件有改动(比如说重新生成)pdb文件就必须做相应改变。pdb文件也比较大,程序运行时也会因为要完成映射而比较慢,这也是release版与debug的区别。

对于dll文件的使用,将dll文件拷贝到工程debug文件下,或者在系统环境变量中加入dll文件的路径(...\bin)。

(1)附加依赖项配置

类似静态库的使用,直接在vs中进行配置。(其实本质还是隐式链接,只是配置方式不同)

(2)隐式链接

第一种方法是:通过project->link->Object/LibraryModule中加入.lib文件(或者在源代码中加入指令#pragma comment(lib, “Lib.lib”)),并将.dll文件置入工程所在目录,然后添加对应的.h头文件。

 #include "stdafx.h"
#include "DLLSample.h" #pragma comment(lib, "DLLSample.lib") //你也可以在项目属性中设置库的链接 int main()
{
TestDLL(); //dll中的函数,在DllSample.h中声明
return();
}

(3)显式链接

还有一种方式是调用windows的api LoadLibrary来加载dll,并根据头文件调用GetProcAddress 加载dll中的函数,最后使用FreeLibrary释放,这种方式显然不可以调试。需要函数指针和WIN32 API函数LoadLibrary、GetProcAddress装载,使用这种载入方法,不需要.lib文件和.h头文件,只需要.dll文件即可(将.dll文件置入工程目录中)。

 #include <iostream>
#include <windows.h> //使用函数和某些特殊变量
typedef void (*DLLFunc)(int);
int main()
{
DLLFunc dllFunc;
HINSTANCE hInstLibrary = LoadLibrary("DLLSample.dll"); if (hInstLibrary == NULL)
{
FreeLibrary(hInstLibrary);
}
dllFunc = (DLLFunc)GetProcAddress(hInstLibrary, "TestDLL");
if (dllFunc == NULL)
{
FreeLibrary(hInstLibrary);
}
dllFunc();
std::cin.get();
FreeLibrary(hInstLibrary);
return();
}

LoadLibrary函数利用一个名称作为参数,获得DLL的实例(HINSTANCE类型是实例的句柄),通常调用该函数后需要查看一下函数返回是否成功,如果不成功则返回NULL(句柄无效),此时调用函数FreeLibrary释放DLL获得的内存。
GetProcAddress函数利用DLL的句柄和函数的名称作为参数,返回相应的函数指针,同时必须使用强转;判断函数指针是否为NULL,如果是则调用函数FreeLibrary释放DLL获得的内存。此后,可以使用函数指针来调用实际的函数。
最后要记得使用FreeLibrary函数释放内存。

注意:应用程序如何找到DLL文件?

使用LoadLibrary显式链接,那么在函数的参数中可以指定DLL文件的完整路径;如果不指定路径,或者进行隐式链接,Windows将遵循下面的搜索顺序来定位DLL:
(1)包含EXE文件的目录
(2)工程目录
(3)Windows系统目录
(4)Windows目录
(5)列在Path环境变量中的一系列目录

.lib .dll 区别介绍、使用(dll的两种引入方式)的更多相关文章

  1. Ajax的get和post两种请求方式区别

    Ajax的get和post两种请求方式区别 (摘录):http://ip-10000.blog.sohu.com/114437748.html 解get和post的区别. 1. get是把参数数据队列 ...

  2. form表单中get和post两种提交方式的区别

    一.form表单中get和post两种提交方式的区别? 1.get提交表单中的内容在链接处是可见的.post不可见 2.post相比于get是安全的 3.post不收限制大小,get有限制大小(黑马视 ...

  3. Java中String对象两种赋值方式的区别

    本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...

  4. java的两种同步方式, Synchronized与ReentrantLock的区别

    java在编写多线程程序时,为了保证线程安全,需要对数据同步,经常用到两种同步方式就是Synchronized和重入锁ReentrantLock. 相似点: 这两种同步方式有很多相似之处,它们都是加锁 ...

  5. 关于springboot项目的jar和war两种打包方式部署的区别

    关于springboot项目的jar和war两种打包方式部署的区别 关于springboot项目的jar和war两种打包方式部署的区别? https://bbs.csdn.net/topics/392 ...

  6. snappy-java两种压缩方式的区别

    1.Snappy-java项目地址 https://github.com/xerial/snappy-java 2.Snappy-java两种压缩方式 使用Snappy.compress进行压缩 St ...

  7. iOS- 网络请求的两种常用方式【GET & POST】的区别

    GET和POST 网络请求的两种常用方式的实现[GET & POST] –GET的语义是获取指定URL上的资源 –将数据按照variable=value的形式,添加到action所指向的URL ...

  8. Docker + .NET Core(三)-两种发布方式

    原文:Docker + .NET Core(三)-两种发布方式 第一种,自己手写dockerfile发布,上传至hubDocker 正常发布到文件夹中,发布文件上传至linux机器上.如 /www/a ...

  9. Adobe Acrobat XI Pro 两种破解方式 Keygen秘钥 license替换 亲测有效

    大家平时看paper比较多的话想必都是用Adobe Acrobat而非Adobe Reader吧,其功能全面之处就不啰嗦了,下面给大家分享下Adobe Acrobat XI Pro的两种破解方式(两种 ...

随机推荐

  1. leetcode的Hot100系列--序

    小白程序猿,练练手,做做题目,分享下经验, 有不对的,还请大家能够指出,多多包涵!谢谢!! 先简单,后复杂,循序渐进,希望能够坚持下来, 大家一起进步~~

  2. 在CentOS7环境下安装Mysql

    1.wget http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm // 下载mysql yum源 2.rpm -i ...

  3. 查询IP地址的免费API

    1.百度 1.http://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=192.168.0.0&co=&resource_ ...

  4. S7 300数据块中的变量指定断电保持特性

    利用DB块内变量属性的保持性,勾选上就可以保持了.300PLC数据块默认断电保持.

  5. .Net Core 通用主机(Core 在控制台应用程序中的应用)

    一.介绍 官方文档中说,Microsoft.AspNetCore.App 元包(ASP.NET Core 2.1 或更高版本)包含通用主机的Microsoft.Extensions.Hosting包, ...

  6. 拓扑排序 (Topological Sorting)

    拓扑排序(Topological Sorting) 一.拓扑排序 含义 构造AOV网络全部顶点的拓扑有序序列的运算称为拓扑排序(Topological Sorting). 在图论中,拓扑排序(Topo ...

  7. 剑指offer第二版-7.重建二叉树

    描述:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树.假设前序遍历或中序遍历的结果中无重复的数字. 思路:前序遍历的第一个元素为根节点的值,据此将中序遍历数组拆分为左子树+root+右子树,前序遍 ...

  8. 学习2:总结# 1.while # 2.字符串格式化 # 3.运算符 # 4.编码初始

    目录 1.while循环 -- 死循环 2.字符串格式化: 3.运算符 4.编码 1.while循环 -- 死循环 while 条件: 循环体 打断死循环: break -- 终止当前循环 改变条件 ...

  9. Junit初级应用实例

    Request: public interface Request { String getName(); } Response: public interface Response { String ...

  10. javascript之正则表达式(二)

    js正则贪婪模式与非贪婪模式 类似于贪吃蛇游戏,越吃越长.而贪婪模式就是尽可能多的匹配. 默认是贪婪模式      (尽可能多的匹配)                           例子: va ...