VC.Net中创建与使用静态链接库(lib)和动态链接库(dll),以及它们的区别

VC.Net中创建与使用静态链接库(lib)和动态链接库(dll),以及它们的区别.
使用静态库需要h文件和.lib,在项目中使用静态库需要以下步骤:
1.在项目中包含相应的静态库头文件.
2.在项目中加入静态库,有两种方法:
方法一:项目设置中引用.lib,Project-Property-Configuration Properties-link-Input-Additional Dependencies中添加.lib.
方法二: 在代码使用 #progma comment(lib,"lib文件名");
3.使用静态库中的函数.
一个静态链接库的例子:
创建一个空项目或Dll项目命名为UseLib.
项目设置(VC2005.Net):
Project-Property-Configuration Properties - General - Project Defaults - Configuration Type 选择 Static Library(.lib)

  1. //代码示例   
  2. //UseLib.h   
  3. #pragma once   
  4. #ifdef __cplusplus   
  5. extern   "C"  {  
  6. #endif   
  7.   
  8.     int  GetMin( int  a,  int  b);  
  9.   
  10. #ifdef __cplusplus   
  11. }  
  12. #endif   
  13.   
  14. //UseLib.cpp   
  15. #include "UseLib.h"   
  16. int  GetMin( int  a,  int  b)  
  17. {  
  18.     return  (a < b) ? a : b;  
  19. }  
  20. //编译.   
  21.   
  22. //然后在创建一个控制台程序,用于测试静态库.   
  23. //main.cpp   
  24. #include "../UseLib /UseLib.h"                //这是包含.h.请更改为你的.h路径.   
  25. #pragma comment(lib, "../lib/UseLib.lib")   //这是包含.lib.请更改为你的.lib路径.   
  26. int  main( int  argc,  char * argv[])  
  27. {  
  28.     int  a = 11, b = 12, c = 0;  
  29.   
  30.     c = GetMin(a, b);  
  31.     return  0;  
  32. }  

动态链接库一般包括.lib(导出函数),.h,.dll,使用动态库有两种情况:

1加载时的隐式链接,同使用静态库相似,分为三步:包含.h和引用.lib,使用导出函数;这种方法是在程序运行开始就将dll库载入内存, 所以如果程序运行时找不到dll文件将导致程序启动失败.

2运行时的显式链接,直接使用LoadLibrary 加载所需的动态库,然后指定所需的导出函数. 这种方法不需要动态链接库的.h和.lib文件.

LoadLibrary函数映射DLL文件映像到进程地址空间, 失败返回NULL,通过GetLastError()可以获得相关错误.
GetProcAddress函数使用函数名字取得函数的地址。利用该函数地址,就可以访问动态连接库的函数了。返回NULL表示获取失败.通过GetLastError()可以获得相关错误.
FreeLibrary通过检查动态连接库的引用计数器,判断是否还有别的程序在使用这个动态连接库。如果没有,就从内存中移去该动态连接库;如果有,将动态连接库的使用计数器减1。LoadLibrary则将引用计数加1。

一个动态链接库的例子:
创建一个空项目或Dll项目命名为UseDll.
项目设置(VC2005.Net):
Project-Property-Configuration Properties - General - Project Defaults - Configuration Type 选择 Dynamic Library (.dll)
Project-Property-Configuration Properties - C/C++ - Preprocessor- Preprocessor Definitions 添加 _USRDLL

  1. //UseDll.h   
  2. #ifdef _USRDLL   
  3. #define DllAPI extern "C" __declspec(dllexport)   
  4. #else   
  5. #define DllAPI extern "C" __declspec(dllimport)   
  6. #endif   
  7. DllAPI int  GetMin( int  a,  int  b);   
  8.   
  9. //UseDll.cpp   
  10. #include "UseDll.h"   
  11.   
  12. DllAPI int  GetMin( int  a,  int  b)  
  13. {  
  14.     return  (a < b) ? a : b;  
  15. }  
  16.   
  17.   
  18. //然后在创建一个控制台程序,用于测试动态链接库.   
  19. //main.cpp   
  20. #include "windows.h"   
  21. #include <stdio.h>   
  22.   
  23. //1表示使用隐式链接.   
  24. //0表示使用显式链接.   
  25. #define StaticLink  0   
  26.   
  27. #if StaticLink   
  28. #include "../UseDll /UseDll.h"                    //这是包含.h.请更改为你的.h路径.   
  29. #pragma comment(lib,"../lib/UseDlld.lib")     //这是包含.lib.请更改为你的.lib路径.   
  30. #endif   
  31.   
  32. int  main( int  argc,  char * argv[])  
  33. {  
  34.     int  a = 11, b = 12, c = 0;  
  35.   
  36. #if StaticLink   
  37.     c = GetMin(a,b);  
  38.     /*  
  39.     使用隐式链接注意事项,需要把.dll放到系统能找到的地方.下面加载dll的搜索顺序:      
  40.     1) 包含可执行映像文件的目录。  
  41.     2) 进程的当前目录。  
  42.     3) Windows系统目录。  
  43.     4) Windows目录。  
  44.     5) PATH环境变量中列出的各个目录。  
  45.     */   
  46. #else   
  47.     typedef   int   (*LPFNDLLFUNC)( int  , int );  
  48.     LPFNDLLFUNC lpfnDllFunc;   
  49.   
  50.     HINSTANCE  hInst = LoadLibrary( "../lib/UseDlld.dll" );  //请更改为你的.dll路径.   
  51.   
  52.     if  (hInst == NULL)  
  53.     {  
  54.         printf("err: %d" , GetLastError());  
  55.         return  1;  
  56.     }  
  57.   
  58.     lpfnDllFunc = (LPFNDLLFUNC)GetProcAddress(hInst, "GetMin" );  
  59.   
  60.     if  (lpfnDllFunc == NULL)  
  61.     {  
  62.         printf("err: %d" , GetLastError());  
  63.         FreeLibrary(hInst);  
  64.         return  1;  
  65.     }  
  66.   
  67.     //调用GetMin   
  68.     c = lpfnDllFunc(a, b);  
  69.     FreeLibrary(hInst);  
  70. #endif   
  71.   
  72.     printf("GetMin( %d, %d): %d" ,a, b, c);  
  73.     return  0;  
  74. }  

通过示例我们可以看出,静态链接库的使用方法和隐式链接十分相似,它们都用到了.lib文件.这里一下说明他们.lib文件的区别:
静态库.lib它包含了变量和函数的实现。作为动态链接库的.lib不包含任何函数和变量,它只是列出所有已输出的函数和变量的符号名.

动态链接库和静态链接库的区别:
静态链接库在编译期把所有的代码和数据都生成到执行程序,运行时就不再需要库了。
动态链接库在编译期只建立一个引用的接口,而真正的代码和数据存放在另外的可执行模块中,在运行时再装入.

隐式链接和显式链接的区别:
隐式链接:程序在启动时就加载DLL模块.直到程序结束时才卸载DLL模块.在此期间可以直接调用Dll的函数等.
显式链接:在调用LoadLibrary()时才加载DLL模块,要使用函数通过GetProcessAddress()来得函数址址.调用FreeLibrary()就可以释放DLL资源.

(程序示例使用VC2005.Net编译通过. 欲知更多相关DLL信息可以参看windows核心编程第四部分(动态链接库).)

 

 

目前以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 3.1 使用 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 函数调用的原理。

LIB 创建标准库、导入库和导出文件,在生成 32 位程序时可将它们与 LINK 一起使用。LIB 从命令提示运行。
可在下列几种模式下使用 LIB:
生成或修改 COFF 库
将成员对象提取到文件中
创建导出文件和导入库
这些模式是互斥的;每次只能以一种模式使用 LIB。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值