`

VC++动态链接库(DLL)编程入门

阅读更多
什么是动态链接库?

一、动态链接库的概念
  动态链接库(Dynamic Link Library,缩写为DLL)是一个可以被其它应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源。动态链接库文件的扩展名一般是dll,也有可能是drv、sys和fon,它和可执行文件(exe)非常类似,区别在于DLL中虽然包含了可执行代码却不能单独执行,而应由Windows应用程序直接或间接调用。

  动态链接是相对于静态链接而言的。所谓静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。换句话说,函数和过程的代码就在程序的exe文件中,该文件包含了运行时所需的全部代码。当多个程序都调用相同函数时,内存中就会存在这个函数的多个拷贝,这样就浪费了宝贵的内存资源。而动态链接所调用的函数代码并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息(往往是一些重定位信息)。仅当应用程序被装入内存开始运行时,在Windows的管理下,才在应用程序与相应的DLL之间建立链接关系。当要执行所调用DLL中的函数时,根据链接产生的重定位信息,Windows才转去执行DLL中相应的函数代码。

  一般情况下,如果一个应用程序使用了动态链接库,Win32系统保证内存中只有DLL的一份复制品,这是通过内存映射文件实现的。DLL首先被调入Win32系统的全局堆栈,然后映射到调用这个DLL的进程地址空间。在Win32系统中,每个进程拥有自己的32位线性地址空间,如果一个DLL被多个进程调用,每个进程都会收到该DLL的一份映像。与16位Windows不同,在Win32中DLL可以看作是每个进程自己的代码。

  二、动态链接库的优点

  1. 共享代码、资源和数据

   使用DLL的主要目的就是为了共享代码,DLL的代码可以被所有的Windows应用程序共享。

  2. 隐藏实现的细节

   DLL中的例程可以被应用程序访问,而应用程序并不知道这些例程的细节。

  3. 拓展开发工具如Delphi的功能

  由于DLL是与语言无关的,因此可以创建一个DLL,被C++、VB或任何支持动态链接库的语言调用。这样如果一种语言存在不足,就可以通过访问另一种语言创建的DLL来弥补。

  三、动态链接库的实现方法

  1. Load-time Dynamic Linking

  这种用法的前提是在编译之前已经明确知道要调用DLL中的哪几个函数,编译时在目标文件中只保留必要的链接信息,而不含DLL函数的代码;当程序执行时,利用链接信息加载DLL函数代码并在内存中将其链接入调用程序的执行空间中,其主要目的是便于代码共享。

  2. Run-time Dynamic Linking

  这种方式是指在编译之前并不知道将会调用哪些DLL函数,完全是在运行过程中根据需要决定应调用哪个函数,并用LoadLibrary和GetProcAddress动态获得DLL函数的入口地址。



教你认识动态链接库DLL文件


  DLL是Dynamic Link Library的缩写,意为动态链接库。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可有多个DLL文件,一个DLL文件也可能被几个应用程序所共用,这样的DLL文件被称为共享DLL文件。DLL文件一般被存放在C:WindowsSystem目录下。


  1、如何了解某应用程序使用哪些DLL文件

  右键单击该应用程序并选择快捷菜单中的“快速查看”命令,在随后出现的“快速查看”窗口的“引入表”一栏中你将看到其使用DLL文件的情况。

  2、如何知道DLL文件被几个程序使用

  运行Regedit,进入HKEY_LOCAL_MACHINESoftwareMicrosrftWindowsCurrent-
VersionSharedDlls子键查看,其右边窗口中就显示了所有DLL文件及其相关数据,其中数据右边小括号内的数字就说明了被几个程序使用,(2)表示被两个程序使用,(0)则表示无程序使用,可以将其删除。

  3、如何解决DLL文件丢失的情况

  有时在卸载文件时会提醒你删除某个DLL文件可能会影响其他应用程序的运行。所以当你卸载软件时,就有可能误删共享的DLL文件。一旦出现了丢失DLL文件的情况,如果你能确定其名称,可以在Sysbckup(系统备份文件夹)中找到该DLL文件,将其复制到System文件夹中。如果这样不行,在电脑启动时又总是出现“***dll文件丢失……”的提示框,你可以在“开始/运行”中运行Msconfig,进入系统配置实用程序对话框以后,单击选择“System.ini”标签,找出提示丢失的DLL文件,使其不被选中,这样开机时就不会出现错误提示了。


什么是DLL
DLL是一个包含可由多个程序同时使用的代码和数据的集合。例如,在Windows操作系统中,Comdlg32 DLL执行与对话框有关的常见函数。因此,每个程序都可以使用该DLL中包含的功能来实现“打开”对话框。这有助于促进代码重用和内存的有效使用。
通过使用DLL,程序可以实现模块化,由相对独立的组件组成。例如,一个计帐程序可以按模块来销售。可以在运行时将各个模块加载到主程序中(如果安装了相应模块)。因为模块是彼此独立的,所以程序的加载速度更快,而且模块只在相应的功能被请求时才加载。

DLL的优点
1. 使用较少的资源。当多个程序使用同一个函数库时,DLL可以减少在磁盘和物理内存中加载的代码的重复量。这不仅可以大大影响在前台运行的程序,而且可以大大影响其他在Windows操作系统上运行的程序。
2. 简化部署和安装。当DLL中的函数需要更新或修复时,只要函数的参数和返回值没有更改,就不需重新编译或重新建立程序与该DLL的链接。此外,如果多个程序使用同一个DLL,那么多个程序都将从该更新或修复中获益。
3. 支持多语言程序。只要程序遵循函数的调用约定,用不同编程语言编写的程序就可以调用相同的DLL函数。程序与DLL函数在下列方面必须是兼容的:函数期望其参数被推送到堆栈上的顺序,是函数还是应用程序负责清理堆栈,以及寄存器中是否传递了任何参数。
4. 使国际版本的创建轻松完成。通过将资源放到DLL中,创建应用程序的国际版本变得容易得多。可将用于应用程序的每个语言版本的字符串放到单独的DLL资源文件中,并使不同的语言版本加载合适的资源。

DLL的类型(Kinds of DLLs)
Visual C++支持三种类型的DLL,它们分别是Non-MFC DLL、MFC Regular DLL、MFC Extension DLL。
1. Non-MFC DLL指的是不用MFC的类库结构,直接用C语言写的DLL,其导出的函数是标准的C接口,能被MFC或非MFC编写的客户程序调用。
2. Extension DLL支持C++接口,也就是说它导出C++函数或者整个类给客户程序。导出函数可以使用C++或MFC的数据形式作为参数或返回值,当导出整个类时,客户程序可以创建此类的对象或者从这些类进行派生。使用Extension DLL的一个问题就是该DLL仅能和MFC客户程序一起工作。
3. Regular DLL和上述的Extension Dll一样,也是用MFC类库编写的,它的一个明显的特点是在源文件里有一个继承CWinApp的类(注意:此类DLL虽然从CWinApp派生,但没有消息循环)。Regular DLL有一个很大的限制就是,它可以导出C风格的函数,但不能导出C++类、成员函数或重载函数。调用Regular DLL的客户程序不必是MFC应用程序。
它们可以是在Visual C++、Dephi、Visual Basic等编译环境下开发的客户程序。

DLL的加载
客户程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接。
1. 隐式链接(静态加载或加载时动态链接)
为了隐式链接到DLL,客户程序必须从DLL的提供程序获取下列各项:
a. 包含导出函数或C++类声明的头文件(.h文件)
b. 要链接的导入库(.lib文件)
c. 实际的DLL(.dll文件)
使用DLL的客户程序必须include头文件(此头文件包含每个DLL中的导出函数或C++类),并且链接到此DLL的创建者所提供的导入库。
// Cacl.cpp
...
DLLAPI int Sum(int a, int b)
{
    return a + b;
}

// Cacl.h
#ifdef CACL_EXPORTS
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif

DLLAPI int Sum(int a, int b);

// Client.cpp
DLLAPI int sum(int a, int b);
...

2. 显式链接(动态加载或运行时动态链接)
在显式链接下,客户程序必须进行函数调用以在运行时显式加载DLL。为显式链接到DLL,客户程序必须:
a. 调用LoadLibrary加载DLL和获取模块句柄
b. 调用GetProcAddress获取指向客户程序要调用的每个导出函数的函数指针(由于客户程序是通过指针调用DLL的函数,编译器不生成外部引用,故无需与导入库链接)
c. 使用完DLL后调用FreeLibrary释放资源
// Client.cpp
HINSTANCE hDLL = LoadLibrary("demo");
if (hDLL != NULL)
{
    LPFNDLLFUNC1 lpfnDllFunc1 = GetProcAddress(hDLL, "Sum");
    if (lpfnDllFunc1 == NULL)
    {
        FreeLibrary(hDLL);
        return SOME_ERROR_CODE;
    }
    return lpfnDllFunc1(dwParam, uParam);
}

客户程序如何找到DLL
如果用LoadLibrary显示链接到DLL的话,我们可以指定DLL的全路径名。如果没有指定路径名,或者用了隐式链接,则Windows将使用下面的搜索序列来定位DLL:
1. 包含客户EXE文件的目录
2. 当前目录
3. Windows系统目录(GetSystemDirectory)
4. Windows目录(GetWindowsDirectory)
5. 在Path环境变量里列出的目录(注意:未使用LIBPATH环境变量)

导出DLL函数
DLL文件的布局与EXE文件非常相似,但有一个重要差异:DLL文件包含导出表。导出表包含DLL导出到客户程序的每个函数的名称。只有导出表中的函数可由客户程序访问。DLL中的任何其他函数都是DLL私有的。通过使用带/EXPORTS选项的Dumpbin工具,可以查看DLL的导出表。
有两种从DLL导出函数的方法:
1. 在函数的定义中使用__declspec(dllexport)关键字
使用__declspec(dllexport)关键字可以从DLL中导出数据、函数、类或类成员函数。如果要导出函数,__declspec(dllexport)关键字必须出现在调用约定关键字()的左边(如果指定了关键字)。例如:
__declspec(dllexport) void __cdecl Function();


若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边,如下所示:
class __declspec(dllexport) CExampleExport : public CObject
{
    ...
};

2. 在生成DLL时,创建一个模块定义(.def)文件并使用此DEF文件。(如果希望按序号而不是按名称从DLL导出函数,则使用此方法。)

示例DLL和客户程序
// Cacl.h
#ifdef CACL_EXPORTS
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif

DLLAPI int Sum(int a, int b);

// Cacl.cpp
#include <windows.h>
#include "Cacl.h"

BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
{
    switch (reason)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

DLLAPI int Sum(int a, int b)
{
    return a + b;
}

// Client.cpp
#include <stdio.h>
#include "Cacl.h"

int main(int argc, char* argv[])
{
    printf("Sum = %d\n", Sum(5, 3));
    return 0;
}
如何调试DLL
调试DLL很容易,只要从DLL工程启动调试器即可。第一次这样做的时候,调试器会请求给出客户EXE程序的路径。之后,每次从调试器运行DLL时,调试器会自动装入客户EXE程序,而EXE用搜索序列找到DLL。

分享到:
评论

相关推荐

    VC++ 动态链接库 (DLL) 编程.pdf

    VC++ 动态链接库 (DLL) 编程 从概念到编码的详细介绍

    VC++动态链接库(DLL)编程深入浅出

    在讨论VC++动态链接库(DLL)编程的深入浅出之前,首先需要对DLL进行基本的概念阐述。动态链接库DLL是一种特殊的程序,它提供变量、函数或类供其他程序使用。与静态链接库不同的是,DLL中的代码不需要直接包含在最终的...

    VC++数据库编程.pdf/VC++深入详解.pdf/VC++动态链接库(DLL)编程.pdf

    在给定的压缩包文件中,我们关注的焦点主要集中在三个主题上:VC++数据库编程、VC++动态链接库(DLL)编程以及深入理解VC++的相关知识。这些资源提供了广泛的信息,帮助开发者深入掌握Microsoft Visual C++(VC++)的...

    VC++DLL编程入门

    ### VC++ DLL编程入门知识点详解 #### 一、概述 **动态链接库(Dynamic Linkable Library,DLL)** 是一种可被多个程序同时使用的代码和数据集合,它为应用程序提供了可重用的功能。通过使用DLL,可以实现代码的...

    VC++_Win32 编程入门

    标题《VC++_Win32 编程入门》指出了文章的主题是介绍使用C++语言进行Windows编程的初学者入门指南,且仅覆盖Win32 API编程部分,不涉及MFC(Microsoft Foundation Classes)框架。Win32 API是Windows操作系统提供的...

    C++动态链接库编程经典文档

    在编程世界中,动态链接库(DLL)是一种重要的技术,...《VC++动态链接库(DLL)编程深入浅出.pdf》这份文档应该会进一步深入这些主题,提供更详细的指导和实例。学习和实践这些概念将对提升C++开发者的技能大有裨益。

    图文手把手教你一步步用VC 2010编写通达信缠论插件(1-DLL设计入门).pdf

    1. VC++ 2010开发环境的使用方法:文件中提到了如何使用Visual C++ 2010创建新的Win32项目,并且设置应用程序类型为DLL,这是编写动态链接库(DLL)的基础步骤。 2. DLL的创建和结构:文档中详细描述了创建DLL项目...

    【VC++2010入门经典_第20章_DLL编程工程源代码-ExtDLLExample】.zip

    《VC++2010入门经典》是一本深入浅出介绍Microsoft Visual C++ 2010编程技术的书籍,而第20章专门讲解了DLL(动态链接库)编程。DLL是Windows操作系统中的一种机制,它允许多个应用程序共享同一段代码和数据,从而...

    VC++ 6.0程序设计从入门到精通

    3. **动态链接库(DLL)**:VC++ 6.0也支持创建DLL项目,它们可以被多个应用程序共享,提高代码重用性。 **四、编程基础** 1. **C++语法**:包括变量、数据类型、运算符、流程控制语句、函数、类与对象、继承、多态...

    Write a DLL in VC++

    ### 动态链接库(DLL)教程:使用VC++ 编写DLL #### 概述 动态链接库(Dynamic Link Library,简称DLL)是Windows操作系统中的一个重要组成部分,它允许程序共享代码和其他资源。通过创建DLL,开发人员可以将常用...

    21天自学vc++,轻轻松松入门

    此外,可能会涉及到动态链接库(DLL)的使用,以及内存管理和异常处理等高级话题。 最后一天,通常会总结学习内容,进行一些实践项目,例如编写一个简单的计算器程序或者文件管理系统,以巩固所学知识,并提供实际...

    VC++6.0从入门到精通.pdf

    8. **动态链接库(DLL)**:了解DLL的作用和创建过程,以及如何在程序中导入和导出DLL函数。 9. **调试技巧**:学习使用VC++6.0的调试工具,包括设置断点、单步执行、查看内存和变量状态等。 10. **异常处理**:...

    VC++6.0从入门到精通

    学习MFC可以帮助你理解窗口、控件、消息处理机制以及如何创建动态链接库(DLL)。 五、GUI编程 在VC++6.0中,你可以使用MFC库来创建用户界面,包括窗口、菜单、对话框、按钮、列表视图等元素。通过事件驱动编程,你...

    vc++入门教程详解

    在VC++中,我们还会接触到动态链接库(DLL)、静态库和头文件的使用,这些都是共享代码和实现模块化的重要方式。此外,了解异常处理和内存管理也是关键,包括智能指针的使用、动态内存分配与释放,以及防止内存泄漏...

    vc 入门控件编程高手

    7. **高级MFC话题**:可能包括多线程、动态链接库(DLL)、国际化和本地化等复杂主题。 8. **实践案例**:提供实际的编程示例,帮助读者将理论知识应用到实践中,巩固所学。 通过这两份教程,学习者可以系统地掌握...

    VC++ MFC入门简明教程

    8. **动态链接库(DLL)支持** MFC支持创建和使用DLL,可以将代码模块化,提高代码重用性和程序性能。 9. **数据库访问** MFC通过ODBC(Open Database Connectivity)提供数据库访问功能。CDatabase和CRecordset...

    VC++多媒体课件(属于VC++的入门级教材)

    "第Y章DLL(新).ppt"则关注动态链接库(DLL)的使用。DLL是一种可被多个程序共享的代码和数据存储库,它可以减少内存占用并提升性能。学习者将了解到如何创建、导入和导出DLL函数,以及解决与DLL相关的各种问题。 ...

    郁金香VC++外挂编程全集中级篇2.1.6part02

    2.3.1、DLL动态链接库构建,与调用 2.3.2、API与回调函数 2.3.3、DLL中构建窗口 2.4、用OD分析游戏功能CALL.《热血江湖》为例:主要是找CALL 2.4.1、选怪CALL 2.4.2、找游戏物品背包的基址+偏移 2.4.3、 吃红药...

Global site tag (gtag.js) - Google Analytics