参考一:
静态库和动态库的区别
动态库:在目标文件运行时加载,手动加载,且对库有依赖性。
两者区别:
一,静态库的使用需要:
1 包含一个对应的头文件告知编译器lib文件里面的具体内容
2 设置lib文件允许编译器去查找已经编译好的二进制代码
二,动态库的使用:
程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库
三,依赖性:
静态链接表示静态性,在编译链接之后, lib库中需要的资源已经在可执行程序中了, 也就是静态存在,没有依赖性了
动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供 需要的 动态库,有依赖性, 运行时候没有找到库就不能运行了
四,区别:
简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。
做成静态库可执行文件本身比较大,但不必附带动态库
做成动态库可执行文件本身比较小,但需要附带动态库
五:
首先纠正所谓“静态连接就是把需要的库函数放进你的exe之中”的说法。在真实世界中,有三个概念:Use static libary, static linked DLL, dynamic linked DLL.
多数人混淆了static libary 和 static linked DLL的概念,当然他们有似是而非的“相似之处”,比如都用到.lib,下面具体说明。
使用静态库(Use static libary)是把.lib和其他.obj一起build在目标文件中,目标文件可以是.exe,也可以是.dll或.oxc等。一般情况下,可以根本就没有“对应的”.dll 文件,如C Run Time(CRT)库。一个例子就是,写一个main(){},build出来并不是只有几个字节,当然有人会说那还有exe文件头呢?是,即使加上文件头的尺寸,build出的执行文件仍然“莫名的大”。实际上那多出来的部分就是CRT静态库。姑且可以把静态库.lib理解成外部程序的obj文件比较合理,它包含了函数的实现。
下面再谈static linked DLL 和 dynamic linked DLL又如何?
静态链接 (static linked DLL)从操作上在VC的Project|Settings...|Link (tab)|General (category)|Object/library modules 中设置和添加。比如要使用SDK中的PropertySheet() API, 就要在这里添加 comctl32.lib,然后再调用的源程序中#include <prsht.h> , 使用的地方直接调用PropertySheet()。当程序.exe启动时,系统会把对应comctl32.dll加载进来。作为DLL的静态引入库的.lib不包含函数的实现,只包含用于系统加载的信息,如对应的DLL名称,函数歧视地只在对应的DLL中的便宜等等。相比动态链接而言,静态链接是很简单的。
动态链接是使用LoadLibrary()/GetProcessAddress()和FreeLibrary(),详见下面的例子。
{
typedef BOOL (WINAPI *LPFNSHELLEXECUTEEX)(LPSHELLEXECUTEINFO);
hShell32Dll = LoadLibrary(TEXT( "SHELL32.DLL "));
if (!hShell32Dll) { goto End; }
lpfnShellExecuteEx = (LPFNSHELLEXECUTEEX)GetProcAddress(hShell32Dll,
API_NAME(ShellExecuteEx));
if (!lpfnShellExecuteEx) { goto End; }
...
fOk = (*lpfnShellExecuteEx)(pShellExecuteInfo);
...
End:
if (hShell32Dll) {
FreeLibrary(hShell32Dll);
}
lpfnShellExecuteEx = NULL;
...
}
有人会想,动态链接这样麻烦,为什么还要用呢?这里有一个技术问题,对这个问题的解决直接导致了动态加载的需求。问题是有些DLL只在某个Windows版本中存在,或某个API只在某些Windows版本中被加入指定的DLL。当你使用静态链接的.exe试图在不支持的Windows版本上运行时,系统会弹出系统对话框提示某某.dll无法加载或无法定位某某API的消息,然后就中止.exe的运行。像这样因为个别功能的实现依赖于某个DLL,当这个DLL不可用时导致整个.exe无法运行是不明智的。避免这样的结局只有用动态链接。
参考二:
静态库Lib和动态库Dll的区别
静态库会全部链接在exe文件里面,dll可以和exe文件分开;
静态库只会产生一个lib文件,而dll则产生一个导入库lib(只是包含函数符号在dll中的地址,以方便使用)和一个dll文件,使用时放在exe能找到的目录下面;
静态库中不能再包含其他的dll和静态lib,而dll中可以再包含;
对静态库lib的使用就好像是函数是在本个exe文件中定义的一样,只是你看不到,不能对应用的函数加dllimport声明,使用普通声明就可以了,因为如果使用dllimport声明的话,就表明这个函数时从dll中导入的,那么连接器就会去导入库lib去查找函数,而我们又没有这个导入库,所以会出现链接错误。dllimport只能适用于动态链接库。注意静态库lib和dll的导入库lib不是一个东西,虽然名字后缀相同。导入库是用来方便程序静态载入动态链接库的,并没有函数的实现。而静态lib则有,就像是.h和.cpp文件都在你的工程中一样。只是这个.cpp文件你看不到,好像隐身了一样。
导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。
参考三:
C++中动态连接库与静态连接库的区别
静态链接库是.lib格式的文件,一般在工程的设置界面加入工程中,程序编译时会把lib文件的代码加入你的程序中因此会增加代码大小,你的程序一运行lib代码强制被装入你程序的运行空间,不能手动移除lib代码。动态链接库是程序运行时动态装入内存的模块,格式*.dll,在程序运行时可以随意加载和移除,节省内存空间。 在大型的软件项目中一般要实现很多功能,如果把所有单独的功能写成一个个lib文件的话,程序运行的时候要占用很大的内存空间,导致运行缓慢;但是如果将功能写成dll文件,就可以在用到该功能的时候调用功能对应的dll文件,不用这个功能时将dll文件移除内存,这样可以节省内存空间。
参考四:
c++静态库与动态库的区别
一,概念
1)静态链接库就是你使用的.lib文件,库中得代码最后需要连接到你的可执行文件中去,所以静态连接的可执行文件一般比较大一些。
使用方法
1> 格式如:#pragma comment(lib,"XXX.lib")
2> 针对开发环境:
1、如果使用VC,可以在Project Setting-->Link中加入你的静态库,也可以直接把该.lib文件加入到你的工程中
2、如果使用Visual Studio,位置在 项目→配置属性→连接器→输入→附加依赖项 中加入.lib文件
构造方法
在静态库情况下,函数和数据被编译进一个二进制文件(通常扩展名为*.lib),Visual C++的编译器在链接过程中将从静态库中恢复这些函数和数据并把他们和应用程序中的其他模块组合在一起生成可执行文件。这个过程称为"静态链接",此时因为应用程序所需的全部内容都是从库中复制了出来,所以静态库本身并不需要与可执行文件一起发行。
编程使用:使用lib需注意两个文件:
(1).h头文件,包含lib中说明输出的类或符号原型或数据结构。应用程序调用lib时,需要将该文件包含入应用程序的源文件中。
(2).lib文件,见上面。
2)Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内容。DLL 是一个包含可由多个程序同时使用的代码和数据的库。
DLL举例
ActiveX 控件(.ocx) 文件: 示例是日历控件,它使您可以从日历中选择日期。 ·
控制面板(.cpl) 文件 :cpl 文件的一个示例是位于控制面板中的项。每个项都是一个专用 DLL。
· 设备驱动(.drv) 文件
编程使用;
使用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提供,称为动态链接库dynamic link library。
一种是lib包含函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库static link library。
共有两种链接方式:
动态链接使用动态链接库,允许可执行模块(.dll文件或.exe文件)仅包含在运行时定位DLL函数的可执行代码所需的信息。
静态链接使用静态链接库,链接器从静态链接库lib获取所有被引用函数,并将库同代码一起放到可执行文件中。
三,关于lib和dll的区别如下:
(1)lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
(2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
(3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。
使用lib的方法:
静态lib中,一个lib文件实际上是任意个obj文件的集合,obj文件是cpp文件编译生成的。在编译这种静态库工程时,根本不会遇到链接错误;即使有错,也只会在使用这个lib的EXT文件或者DLL工程里暴露出来。
在VC中新建一个static library类型的工程Lib,加入test.cpp文件和test.h文件(头文件内包括函数声明),然后编译,就生成了Lib.lib文件。
别的工程要使用这个lib有两种方式:
(1)在project->link->Object/Library Module中加入Lib.lib文件(先查询工程目录,再查询系统Lib目录);或者在源代码中加入指令#pragma comment(lib, “Lib.lib”)。
(2)将Lib.lib拷入工程所在目录,或者执行文件生成的目录,或者系统Lib目录中。
(3)加入相应的头文件test.h。
使用DLL的方法:
使用动态链接中的lib,不是obj文件的集合,即里面不会有实际的实现,它只是提供动态链接到DLL所需要的信息,这种lib可以在编译一个DLL工程时由编译器生成。
创建DLL工程的方法(略)。
(1)隐式链接
第一种方法是:通过project->link->Object/Library Module中加入.lib文件(或者在源代码中加入指令#pragma comment(lib, “Lib.lib”)),并将.dll文件置入工程所在目录,然后添加对应的.h头文件。
[html]
#include "stdafx.h"
#include "DLLSample.h"
#pragma comment(lib, "DLLSample.lib") //你也可以在项目属性中设置库的链接
int main()
{
TestDLL(123); //dll中的函数,在DllSample.h中声明
return(1);
}
(2)显式链接
需要函数指针和WIN32 API函数LoadLibrary、GetProcAddress装载,使用这种载入方法,不需要.lib文件和.h头文件,只需要.dll文件即可(将.dll文件置入工程目录中)。
[html]
#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(123);
std::cin.get();
FreeLibrary(hInstLibrary);
return(1);
}
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环境变量中的一系列目录