静态链接库与动态链接库区别
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。如果在当前工程中有多处对dll文件中同一个函数的调用,那么执行时,这个函数只会留下一份拷贝。但是如果有多处对lib文件中同一个函数的调用,那么执行时,该函数将在当前程序的执行空间里留下多份拷贝,而且是一处调用就产生一份拷贝。
静态链接库与静态链接库调用规则总体比较如下:
1、 静态链接库(比较简单):
首先,静态链接库的使用需要库的开发者提供生成库的h头文件和lib文件。生成库的h头文件中的声明格式如下:
extern "C" 函数返回类型 函数名(参数表);
在调用程序的cpp源代码文件中如下:
#include "/libh"
#pragma comment(lib,"//debug//libTestlib") //指定与静态库一起链接
其次因为静态链接库是将全部指令都包含入调用程序生成的EXE文件中。因此如果用的是静态链接库,那么也就不存在“导出某个函数提供给用户使用”的情况,要想用就得全要!要不就都别要!
2、 态链接库:
动态链接库的使用需要库的开发者提供生成的lib文件和dll文件。或者只提供dll文件。
首先我们必须先注意到DLL内的函数分为两种:
1) 出函数,可供应用程序调用;
2) LL内部函数,只能在 DLL 程序使用,应用程序无法调用它们。
因此调用程序若想调用DLL中的某个函数就要以某种形式或方式指明它到底想调用哪一个函数。
Ø 对于DLL的导出,可以采用如下方法:
#ifdef WLL_EXPORTS
#define WLL_API __declspec(dllexport)
#else
#define WLL_API __declspec(dllimport)
#endif
这是导出类的宏定义,将导出类必须加上该宏,才能被导出。
此处的WLL_EXPORTS会出现在 projectàsettingsàC++à PreProcessor的PreProcessor definition中,这个MACRO表明其要定义一个导出宏。
当前库编译时,加了WLL_API的类将被导出,而包含该头文件的其他调用DLL或EXE,由于没有定义WLL_API宏,将申明为导入该类。
Ø 动态库函数的调用,可以采用静态链接的方式,主要步骤如下:
包含DLL中导出的头文件。
采用#pragma comment(lib,"//debug//libTestlib")导入动态库生成的lib头文件。或在projectàsettingsàLinkeràInput的Additional Dependencies中加入lib文件。
将动态库生成的dll文件放到EXE或DLL的同一目录下。
Ø 也可以采用动态加载的方式调用,步骤如下:
Anotherdll有一个int Add(int x,int y) 函数。则完整的调用过程如下:
typedef int ( FunPtr)(int,int); //定义函数指针
FunPtr funPtr;
Handle handle =LoadLibrary("Anotherdll");
funPtr =(FunPtr)GetProcAddress(handle ,"Add");
funPtr(2,3); // 2+3;
FreeLibrary(handle); // 释放载入的动态库
LIB文件
目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。
静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。
动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。
导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。
这也是实际上很多开源代码发布的惯用方式:
1、 预编译的开发包:包含一些dll文件和一些lib文件。其中这里的lib就是导入库,而不要错以为是静态库。但是引入方式和静态库一样,要在链接路径上添加找到这些lib的路径。而dll则最好放到最后产生的应用程序exe执行文件相同的目录。这样运行时,就会自动调入动态链接库。
2、 用户自己编译:下载的是源代码,按照readme自己编译。生成很可能也是dll + lib(导入库)的库文件
3、 如果你只有dll,并且你知道dll中函数的函数原型,那么你可以直接在自己程序中使用LoadLibary调入DLL文件,GetProcAddress获取函数地址,然后调用。
DLL文件
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。
动态链接与静态链接的不同之处在于它允许可执行模块(dll 文件或 exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。
使用动态链接代替静态链接有若干优点。DLL 节省内存,减少交换 *** 作,节省磁盘空间,更易于升级,提供售后支持,提供扩展 MFC 库类的机制,支持多语言程序,并使国际版本的创建轻松完成。
API 就是应用程序编程接口。它是能用来 *** 作组件、应用程序或者 *** 作系统的一组函数。典型的情况下,API 由一个或多个提供某种特殊功能的 DLL 组成。
DLL 是一个文件,其中包含了在 Microsoft Windows下运行的任何应用程序都可调用的函数。运行时,DLL 中的函数动态地链接到调用它的应用程序中。无论有多少应用程序调用 DLL 中的某个函数,在磁盘上只有一个文件包含该函数,且只在它调入内存时才创建该 DLL。 您听到最多的 API 可能是 Windows API,它包括构成 Windows *** 作系统的各种 DLL。每个 Windows 应用程序都直接或间接地与 Windows API 互动。Windows API 保证 Windows 下运行的所有应用程序的行为方式一致。
随着 Windows *** 作系统的发展,现已发布了几个版本的 Windows API。Windows 31 使用 Win16 API。Microsoft Windows NT、Windows 95 和 Windows 98平台使用 Microsoft Win32 API。除 Windows API 外,其他一些 API 也已发布。例如,邮件应用程序编程接口 (MAPI) 是一组可用于编写电子邮件应用程序的 DLL。API 传统上是为开发 Windows 应用程序的 C 和 C++ 程序员编写的,但其他的编程语言(包括VBA)也可以调用 DLL 中的函数。因为大部分 DLL 主要是为 C 和 C++ 程序员编写和整理说明的,所以调用 DLL 函数的方法与调用 VBA 函数会有所不同。在使用 API 时必须了解如何给 DLL 函数传递参数。
警告:调用 Windows API 和 其他 DLL 函数可能会给您的应用程序带来不良影响。从自己的代码中直接调用 DLL 函数时,您绕过了 VBA 通常提供的一些安全机制。如果在定义或调用 DLL 函数时出现错误(所有程序员都不可避免),可能会在应用程序中引起应用程序错误(也称为通用性保护错误,或 GPF)。最好的解决办法是在运行代码以前保存该项目,并确保了解 DLL 函数调用的原理。
安装库的时候 sudo 了没 ??
lib 是系统目录,没有 root 权限是无法写入文件的;
顺便问一下,那个 /config --enable-static 命令有什么作用呢 ?
我一般是 sudo make 然后 sudo make install;
可以得出第一个结论:都为静态链接库,有同名函数参与情况下,链接会出现符号多次定义的错误!
两个动态库
再来看看动态链接库,同样的libA libB 生成动态链接库
测试主程序不修改 ! 还是为:
这种编译方式叫做动态库的隐式调用, 如果你删除一个libAso , 运行aout 会出现不能找到动态库的错误
这种情况也可以称为 加载时链接! 静态库属于编译时链接!
可以得出第二个结论: 若都为动态库,并且进行隐式调用,输出结果和动态库的顺序有关
再继续看看动态加载动态库
修改测试主程序
同样可以得出结论,动态链接库如果不加库连选项 ,函数调用是正确的 加库路径,会以库的路径顺序为主! 左边覆盖右边 而且当只链接其中一个时 也生效
两者区别: a,静态库的使用需要: 1 包含一个对应的头文件告知编译器lib文件里面的具体内容 2 设置lib文件允许编译器去查找已经编译好的二进制代码 b,动态库的使用: 程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库 c,依赖性: 静态链接表示静态性,在编译链接之后, lib库中需要的资源已经在可执行程序中了, 也就是静态存在,没有依赖性了 动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供 需要的 动态库,有依赖性, 运行时候没有找到库就不能运行了 d,区别: 简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。 做成静态库可执行文件本身比较大,但不必附带动态库 做成动态库可执行文件本身比较小,但需要附带动态库 链接静态库,编译的可执行文件比较大,当然可以用strip命令精简一下(如:strip libtesta),但还是要比链接动态库的可执行文件大。程序运行时间速度稍微快一点。 静态库是程序运行的时候已经调入内存,不管有没有调用,都会在内存里头。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。 其在编译程序时若链接,程序运行时会在系统指定的路径下搜索,然后导入内存,程序一般执行时间稍微长一点,但编译的可执行文件比较小;动态库是程序运行的时候需要调用的时候才装入内存,不需要的时候是不会装入内存的。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。 动态链接库的特点与优势 首先让我们来看一下,把库函数推迟到程序运行时期载入的好处: 1 可以实现进程之间的资源共享。 什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候, *** 作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。 2 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。 3 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。 程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的 *** 作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写 *** 作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。 静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。 动态库:在目标文件运行时加载,手动加载,且对库有依赖性。 具体在开发中用到哪种库,我觉得还是根据实际的内存大小,ROM大小,运行的速度等综合考虑
一: 隐式的加载时链接,有三种方法
1 LIB文件直接加入到工程文件列表中
在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中"Add Files to Project"菜单,在d出的文件对话框中选中要加入DLL的LIB文件。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "\libh"即可(没有头文件当然就不用了)。
2 设置工程的 Project Settings来加载DLL的LIB文件
打开工程的 Project Settings菜单,选中Link,然后在Object/library modules下的文本框中输入DLL的LIB文件,如youlib(或者lib文件的路径,包括文件名)。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "\libh"即可(没有头文件当然就不用了)。
3 通过程序代码的方式
加入预编译指令#pragma comment (lib,"lib"),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。因为,在Debug方式下,产生的LIB文件是Debug版本,如Regdlib;在Release方式下,产生的LIB文件是Release版本,如Regrlib。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "\libh"即可(没有头文件当然就不用了)。
当应用程序对DLL的LIB文件加载后,还需要把DLL对应的头文件(h)包含到其中,在这个头文件中给出了DLL中定义的函数原型,然后声明
二, 显式的运行时链接 ,(我用的是此方法)
隐式链接虽然实现较简单,但除了必须的dll文件外还需要DLL的h文件和lib文件,在那些只提供dll文件的场合就无法使用,而只能采用显式链接的方式。这种方式通过调用API函数来完成对DLL的加载与卸载,能更加有效地使用内存,在编写大型应用程序时往往采用此方式。这种方法编程具体实现步骤如下:
①使用Windows API函数Load Library或者MFC提供的AfxLoadLibrary将DLL模块映像到进程的内存空间,对DLL模块进行动态加载。
②使用GetProcAddress函数得到要调用DLL中的函数的指针。
③不用DLL时,用Free Library函数或者AfxFreeLibrary函数从进程的地址空间显式卸载DLL。
例:在应用程序中调用dll文件
——在应用程序中要首先装入dll后才能调用导出表中的函数,例如用mfc
创建基于对话框的工程test,并在对话框上放置"load"按钮,先添加装载代码。
1首先在testdlgcpp的首部添加变量设置代码:
//设置全局变量glibsample用于存储dll句柄
HINSTANCE glibsample=null; //如果定义成HANDLE类型,则出错
//第二个变量showme是指向dll
库中showme()函数的指针
typedef int( Showme)(void);
Showme showme;
2利用classwizard为"load"按钮添加装载dll的代码
void ctestdlg::onloadbutton()
{
//要添加的代码如下
if(glibsample!=NULL)
{
AfxMessageBox("the sampledll has already been load");
return;
}
//装载sampledll,未加路径,将在三个默认路径中寻找 (1)windows的系统目录:\windows\system;
//(2)dos中path所指出的任何目录;
//(3)程序所在的目录;
glibsample=Loadlibrary("sampledll");
//返回dll中showme()函数的地址
showme=(Showme)GetProcAddress(glibsample,"showme");
静态链接库LIB和动态链接库DLL的区别
1什么是静态连接库,什么是动态链接库
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接 库。静态链接库与静态链接库调用规则总体比较如下。
对于静态链接库(比较简单):
首先,静态链接库的使用需要库的开发者提供生成库的h头文件和lib文件。
生成库的h头文件中的声明格式如下:
extern "C" 函数返回类型 函数名(参数表);
在调用程序的cpp源代码文件中如下:
#include "\libh"
#pragma comment(lib,"\\debug\\libTestlib")
//指定与静态库一起链接
第二,因为静态链接库是将全部指令都包含入调用程序生成的EXE文件中。因此如果用的是静态链接库,那么也就不存在“导出某个函数提供给用户使用”的情况,要想用就得全要!要不就都别要!:)
对于动态链接库:
动态链接库的使用需要库的开发者提供生成的lib文件和dll文件。或者只提供dll文件。
首先我们必须先注意到DLL内的函数分为两种:
(1)DLL 导出函数,可供应用程序调用;
(2)DLL 内部函数,只能在 DLL 程序使用,应用程序无法调用它们。
因此调用程序若想调用DLL中的某个函数就要以某种形式或方式指明它到底想调用哪一个函数。
以上就是关于lib和dll有什么区别,什么叫静态链接库,什么叫动态连接库全部的内容,包括:lib和dll有什么区别,什么叫静态链接库,什么叫动态连接库、c++程序链接外部库找不到静态库问题、如何确定程序调用了动态库或者静态库等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)