windows中静态库lib和动态dll的区别及使用方法

1. 静态库lib和动态dll的区别

1.1 项目类型

VS在建Win32项目时,有以下选项:

windows应用程序
控制台应用程序
DLL
静态库
最后两个类型:DLL和静态库,这两种项目类型是不可以单独运行的,必须在Windows应用程序调用他们执行,是提供的库函数而已。

1.2 两种lib的区别:

(1)静态库(.lib)

函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件)。当发布产品时,只需要发布这个可执行文件,并不需要发布被使用的静态库。

(2)动态库(.lib文件和.dll文件)

在使用动态库的时候,编译后往往提供两个文件:一个引入库(.lib)文件(也称“导入库文件”)和一个DLL(.dll)文件。当然到了后面会告诉你如果只提供一个DLL文件,使用显示连接的方式也可以调用,只是稍加麻烦而已。

虽然引入库的后缀名也是“lib”,但是,动态库的引入库文件和静态库文件有着本质的区别。对一个DLL文件来说,其引入库文件(.lib)包含该DLL导出的函数和变量的符号名,而.dll文件包含该DLL实际的函数和数据。在使用动态库的情况下,在编译链接可执行文件时,只需要链接该DLL的引入库文件,该DLL中的函数代码和数据并不可复制到可执行文件,直到可执行程序运行时,才去加载所需的DLL,将该DLL映射到进程的地址空间中,然后访问DLL中导出的函数。这时,在发布产品时,除了发布可执行文件以外,同时还需要发布该程序将要调用的动态链接库。

只有当EXE程序确实要调用这些DLL模块的情况下,系统才会将它们装载到内存空间中。这种方式不仅减少了EXE文件的大小和对内存空间的需求,而且使这些DLL模块可以同时被多个应用程序使用。如果DLL不在内存中,系统就将其加载到内存中。当链接Windows程序以产生一个可执行文件时,你必须链接由编程环境提供的专门的 “引入库(import library)”。这些引入库包含了动态链接库名称和所有Windows函数调用的引用信息。链接程序使用该信息在.EXE文件中构造一个表,当加载程序时,Windows使用它将调用转换为Windows函数。

引入库LIb和静态库Lib的区别:

引入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于引入库而言,其实际的执行代码位于动态库中,引入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。但是引入库文件的引入方式和静态库一样,要在链接路径上添加找到这些.lib的路径。

1.3 动态库(Lib和DLL)和静态库Lib的区别:
其实上面已经提到了区别,这里再总结一下:
(1)静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了,最终的可执行文件exe会比较大。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。
(2)静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接 库。静态链接库与静态链接库调用规则总体比较如下。

静态链接库运行之前就加载了,而且一直存在直到关闭程序,动态DLL实在运行时再加载,不用一直占内存,dll模块内部更改了,是要替换Dll即可,方便维护。优点明显,但是dll如果丢失或被误删,就无法运行了

2. 静态库lib和动态dll的使用

2. 1 动态dll的使用

动态链接库的使用需要库的开发者提供生成的.lib文件和.dll文件。或者只提供dll文件。使用时只能使用dll中导出的函数,未导出的函数只能在dll内部使用。Dll的调用有显示连接和隐式连接两种:隐式连接需要三个东西,分别是*.h头文件,lib库(动态的),DLL库;显示连接只需要.dll文件即可。

2.1.1 隐式连接
隐式链接需要三个东西,分别是*.h头文件,lib库(动态的),DLL库,而这里的lib库仅是编译的时候用,运行时候不用,运行时只用Dll

2.1.1.1 添加Lib

方法1: 通过设置工程配置来添加lib库.

A、添加工程的头文件目录:工程->属性->配置属性->c/c++->常规->附加包含目录:加上头文件存放目录。添加头文件参考2.2.1.2
B、添加文件引用的lib静态库路径:工程->属性->配置属性->链接器->常规->附加库目录:加上lib文件存放目录。
C 然后添加工程引用的lib文件名:工程->属性->配置属性->链接器->输入->附加依赖项:加上lib文件名。

这种方法比较繁琐,且不直观,而且还可能要争对debug版本和release版本作不同的配置,因为我们生成的两个版本的库可能放在不同的目录中的.

方法2: 使用编译语句:

#ifdef _DEBUG
#pragma comment(lib,"..\\debug\\LedCtrlBoard.lib")
#else
#pragma comment(lib,"..\\release\\LedCtrlBoard.lib")
#endif
1
2
3
4
5
这种方法直观,方便,且可以按如上直接区分出Debug版本和Release版本的不同目录.当然,通过宏,还可以区分更多版本.但是在指定目录时,不小心容易出错.

方法3: 直接添加库文件到工程中.

就像你添加.h和.cpp文件一样,把lib文件添加到工程文件列表中去.

VC中,切换到”解决方案视图”—>选中要添加lib的工程–>点击右键–>”添加”–>”现有项”–>选择lib文件–>确定.

这个方法适用于在我的工程的debug版本和Release版本中都使用同一个lib库文件时.这样就省去了你1方法配置环境的繁琐,也省去了方法2种语句的可能性错误发生.。

2.1.1.2添加头文件

在调用DLL中导出的函数之前要include对应的头文件,可以写绝对路径,也可以拷贝到工程调用源文件的同一目录下,也可以通过VS添加(include)头文件目录,VS中配置方法:
(1)VS项目->右击属性->配置属性->VC++目录->包含目录
(2)VS项目->右击属性->配置属性->C/C++->常规->附加包含目录

2.1.1.3 添加dll

一般将dll拷贝到运行时目录即可,与调用者exe文件在同一目录,当然有其他方法添加环境变量PATH,
(1)VS项目->右击属性->配置属性->VC++目录->可执行目录
(2)设定DLL目录的位置,具体方法为:项目右击->属性 -> 配置属性 -> 调试 ->工作目录,在这里设置dll的路径就可以了

注1:release版本和debug版本的区分,每种版本的设置都是独立的,要分别设置
注2:单纯添加lib目录的方法有以下几种方法

(1):把.lib文件放在当前使用它的工程目录下;(如:.exe所在目录,或者工程代码所在的目录)
(2):对某一个项目:项目”->“属性”->“配置属性”->“VC++目录”->“常规”->“附加库目录”
(3):在vs中,“项目”->“属性”->“配置属性”->“链接器”->“常规”->“附加库目录”
(4):放在开发环境IDE的lib库目录下,例如:“C:\Program Files\Microsoft Visual Studio 8\VC\lib”,这是vs2005的vc开发的lib库目录。

注:在VS属性中配置路径时可以用绝对路径,也可以用相对路径,其中./表示当前目录,而../表示上一级目录

上面仅仅对单个项目有效,我们配置过opencv库的都知道,有一种是全局配置lib和include头文件,对所有的项目有效,以Debug版为例,步骤如下:
(1) 点击“视图”→“其他窗口”→“属性管理器”
(2) 从左侧项目中打开“Debug| Win32”→“Microsoft.Cpp.Win32.user”
(3) 双击“Microsoft.Cpp.Win32.user”,在弹出的窗口,点击左侧VC++目录,编辑右侧的可执行文件目录、包含目录与库目录,分别添加对应的路径
(4) 附加依赖项,单击“链接器”→“输入”→“附加依赖项”,填入依赖项.lib后缀的文件名。

2.1.2 显示连接

隐式链接虽然实现较简单,但除了必须的.dll文件外还需要DLL的.h文件和.lib文件,在那些只提供.dll文件的场合就无法使用,而只能采用显式链接的方式。这种方式通过调用API函数来完成对DLL的加载与卸载,能更加有效地使用内存,在编写大型应用程序时往往采用此方式。这种方法编程具体实现步骤如下:

①使用Windows API函数Load Library或者MFC提供的AfxLoadLibrary将DLL模块映像到进程的内存空间,对DLL模块进行动态加载。

②使用GetProcAddress函数得到要调用DLL中的函数的指针。

③不用DLL时,用Free Library函数或者AfxFreeLibrary函数从进程的地址空间显式卸载DLL。

使用LoadLibrary显式链接,那么在函数的参数中可以指定DLL文件的完整路径;如果不指定路径,或者进行隐式链接,Windows将遵循下面的搜索顺序来定位搜索DLL:

包含EXE文件的目录
工程目录
Windows系统目录
Windows目录
列在Path环境变量中的一系列目录
2.2 静态库lib的使用

静态lib中,一个lib文件实际上是任意个obj文件的集合,obj文件是cpp文件编译生成的。静态库的.lib文件包含了链接库的所有信息(函数代码和接口信息)。所以我们在调用静态库.lib时,只需要包含头文件目录(../include. .h),以及附加库目录即可。因此,静态链接库的使用需要库的开发者提供生成库的.h头文件和.lib文件

在VC中新建一个static library类型的工程TestLib,加入test.cpp文件和test.h文件(头文件内包括函数声明),然后编译,就生成了TestLib.lib文件。

别的工程要使用这个lib方式:

(1)添加lib
方法1):直接用”项目右击”->”添加”–>”现有项”–>选择lib文件–>确定,通过这种方式将.lib加入工程
方法2):工程属性-> 配置属性->链接器->输入->附加依赖项中添加要使用的Lib库的名字;在工程属性-> 配置属性->链接器->输入->附加库目录中输入.lib文件所在路径(相对或绝对路径)

方法3):或者在源代码中加入指令#pragma comment(lib, “TestLib.lib”),也可以指定完整路径(绝对路径或相对路径)#pragma comment(lib, “..\Debug\TestLib.lib”)。可以通过宏#if defined(_DEBUG)来区分用release或debug版本的lib。另外这里如果不指定完整路径,也要像方法2一样添加附加库目录。

如果不在工程属性中添加附加lib库目录,也可以将静态里边库比如TestLib.lib拷贝到工程所在目录,或者拷贝到执行文件生成的目录,或者拷贝到系统Lib目录中。

(2). 添加头文件

加入相应的头文件test.h。#include “test.h”

include file path可以为绝对路径,也可以为相对于工程所在目录的相对路径,如果头文件比较多,可以在project>settings>c/c++>preprocessor的Additional include directories中填入你的头文件所在目录,编译时会自动在此目录查找头文件。

原文:https://blog.csdn.net/dxzysk/article/details/66477147

原文地址:https://www.cnblogs.com/code1992/p/9777348.html

时间: 2024-10-14 23:18:38

windows中静态库lib和动态dll的区别及使用方法的相关文章

静态链接库LIB和动态链接库DLL的区别 创建和示例

1.什么是静态连接库,什么是动态链接库         静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了.但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件.静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接 库.静态链接库

C语言中静态库和动态库笔记

库 库,故名思议,是存放东西的地方,其中存放的东西可以被多个人公用. 程序中借用库的概念,描述将代码进行抽取,这种代码被大多数程序使用, 其过程具有一定的模块化.封装.抽象的特征. 按照库的使用方式, 静态库 和 动态库. 不管怎样方式使用, 首先库的概念体现出代码逻辑上公共抽象. 有篇博文,做了介绍, 并有例子, 本文纯粹学习,借鉴了其中的例子. http://www.cnblogs.com/chio/archive/2007/11/03/948480.html 静态库 静态库,编译应用程序的

在Linux中创建静态库.a和动态库.so

转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用函数制作成函数库,供其它程序使用. 函数库分为静态库和动态库两种. 1. 静态函数库 这类库的名字一般是libxxx.a:利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译

iOS中静态库-.a文件生成和使用

最近在使用使用一个网上的Demo的时候. 出现另一令人烦恼的问题 . 就是它里面有嵌套的工程. 如下图所示. 工程里面还嵌套有一个工程. 真的是让人煞费苦心 …其实这个问题看起来并不是很难, 如果是一般的工程的话, 解决方法有两种: 我可把嵌套工程里面的文件拖拽出来. 修改一些属性什么的应该可以使用了 还有一种方法就是我把嵌套里面的工程整个生成一个静态库文件.把我需要使用的文件的.h暴露出来使用.但是这个工程比较奇葩. 他里面是c++de一些文件. 如果直接拖拽的话会有各种引用文件错误的问题.

静态库(.a)与动态库(.so)的简明介绍

静态库(.a)与动态库(.so)的简明介绍 gcc有很多关于静态库,动态库的选项如-l,-L,-fPIC,-shared -Wl,-soname,看着很复杂容易混淆,其实静态库和动态库都是应需而生,只要有了一个线索都很容易理解. 普通编译 假设有三个文件(后面均使用这个例子): // mod1.c #include <stdio.h> void print_mod1(){ printf("%s\n",__func__); } // mod2.c #include <s

将静态库制作成动态库

一.系统说明 Ubuntu12.04TLS 64位 二.制作静态库 (1)编写需要制作成静态库的程序(根据实际情况进行编写,这里只是一个简单例子)     //bar.h              #ifndef _BAR_H     #define _BAR_H          void bar(int i);          #endif     //bar.c     #include <stdio.h>     #include <stdlib.h>     #incl

WPF中静态引用资源与动态引用资源的区别

WPF中静态引用资源与动态引用资源的区别 WPF中引用资源分为静态引用与动态引用,两者的区别在哪里呢?我们通过一个小的例子来理解. 点击“Update”按钮,第2个按钮的文字会变成“更上一层楼”,而第1个按钮的文字没有变化. 原因是第1个按钮文字用的是静态引用资源,而第2个按钮文字用的是动态引用资源. 前台代码: <Window x:Class="PersonalLearning.StaticDynamicResourceDemo"        xmlns="http

MFC的亚博静态库.lib、体育动态库.dll以及Unicode库示例

MFC亚博静态库使用下列体育命名约定: uAFXcWd.LIB . 库命名约定的说明符如下: 说明符 值和含义u (n) ANSI 或 (u)Unicodec 创建的计划类型:c=alld d=debug版本; release版本略去说明符默认值为生成用于 Intel 平台的调试版本 windows ANSI 应用程序的静态库:NAFXCWD.Lib. 下表列出的所有库是在 \ atlmfc \ lib 目录中包含预生成的静态库. 静态链接库命名约定: 库 说明NAFXCW.LIB MFC 静态

静态链接库(lib)、动态链接库(dll)与动态链接库的导入库(lib)

静态链接库与动态链接库相对应.动态链接库的导入库不同于以上两种库. 1.静态链接库(lib) 程序编译一般需经编辑.编译.连接.加载和运行几个步骤.在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为"库"文件(lib), 这种LIB中有函数的实现代码.在静态编译时,它是将LIB中的代码加入目标模块(EXE或者DLL)文件中,所以链接好了之后,LIB文件就没有用了. 2.动态链接库(dll) 动态链接库(Dynamic Link Library,缩写为DLL)是一个可以被其