DLL的简单实现及调用

20 篇文章 1 订阅
17 篇文章 1 订阅

DLL(Dynamic  Link Library,动态连接库)是一个可以被其他应用程序调用的应用模块,其中封装了可以被调用的资源或函数。DLL属于可执行文件,他符合Windows系统的PE文件格式,不过他的运行是依附于EXE文件创建的进程来执行的,不能单独运行。一个DLL文件可以被多个进程所装载调用。

DLL是动态连接库,相对应的,是静态连接库。动态连接库是在EXE文件运行时被加载执行的,而静态连接库时OBJ文件进行连接时同时被保存到程序中的。动态连接库可以减少可执行文件的体积,在需要的时候进入内存;将软件划分为多个模块,可以按照模块进行开发,对于发布与升级也非常方便。

DLL程序的编写与运行都有别于常见的命令行程序或Windows程序,无论是函数的入口还是其执行的方式都有差别。

1.   DLL程序的入口不是main函数,也不是WinMain函数,而是DllMain函数,该函数的定义如下:

BOOLAPIENTRY DllMain(

HMODULEhModule,

DWORD ul_reason_for_call,

LPVOIDlpReserved

);

hModule:该参数是当前DLL模块的句柄,即本动态连接库模块的实例句柄。

ul_reason_for_call:该参数表示DllMain函数被调用的原因。

该参数有四种取值,分别为:DLL_PROCESS_ATTACH(当DLL被某进程装载时,调用DllMain);DLL_PROCESS_DETACH(当DLL被某进程卸载时,调用DllMain);DLL_THREAD_ATTACH(当进程中有线程被创建时,调用DllMain);DLL_THREAD_DETACH(当进程中有线程结束时,调用DllMain)。

lpReserved:保留参数,目前不被程序员所使用。


2.在VC6下创建一个DLL工程,步骤如下示:

文件 – > 新建-- > 进入“工程”选项卡。


工程类型选择:Win32Dynamic-Link  Library,指定位置和工程名后点“确定”。


选择“一个简单的DLL工程”然后不断确定就行了。

生成的初始代码如下所示:


其中APIENTRY是一个函数修饰符,定义:#define   APIENTRY   WINAPI

由于DllMain函数不只一次地被调用,根据调用的情况不同,需要执行不同的代码。所以在编写DLL时,一般会将DllMain函数的结构写成如下形式:

BOOL APIENTRY DllMain(HANDLE  hModule,

         DWORD  ul_reason_for_call,

         LPVOIDlpReserved

         )

{

         switch(ul_reason_for_call)

         {

                   case DLL_PROCESS_ATTACH:      //动态库装载是调用

                   {

                                                                                                      

                            break;

                   }

 

                   case DLL_THREAD_ATTACH:       //进程中有线程创建时调用

                   {

                            break;

                   }

 

                   case DLL_THREAD_DETACH:       //进程中有线程结束时调用

                   {

                            break;

                   }

                   case DLL_PROCESS_DETACH:      //动态库卸载是调用

                   {

                            break;

                   }

                  

         }

         returnTRUE;

}

这样可以达到根据不同的调用原因执行不同的代码。


3.为DLL添加一个导出函数

对于DLL文件来说,DllMain并不是必须的。在StdAfx.h中添加导出函数的声明如下:

extern "C" __declspec(dllexport) VOIDMsgBox(char *szMsg);

在StdAfx.cpp中实现该函数如下:

VOID MsgBox(char *szMsg)

{

charszModuleName[MAX_PATH] = { 0 };

GetModuleFileName (NULL,szModuleName, MAX_PATH);

MessageBox (NULL,szMsg, szModuleName, MB_OK);

}

编译、链接后可发现对应debug目录下多出了一些文件,其中firstDLL.Dll和firstDLL.lib是我们后面要用到的。前者是DLL文件,包含编写的代码;后者是一个库文件,其中包含一些导出函数的相关信息。如下图示:


4. DLL程序无法单独运行,需要通过编写一个EXE程序来调用这个DLL文件中的导出函数。下面通过一个简单的程序来调用DLL。

右击“工作区”选择“添加工程到工作空间”。


按以下步骤创建工程:



在新创建的工程中添加一个新的cpp文件,并在其中输入以下代码:

#include<windows.h>

typedef  VOID  (*PFUNMSG)  (char *);

int main()

{

      HMODULE hMoudle =LoadLibrary("firstDLL.dll");

 

      if(hMoudle == NULL)

      {

           MessageBox(NULL, "firstDLL.dll文件不存在!", "DLL文件加载失败", MB_OK);

           return -1;

      }

      PFUNMSG pFunMsg =(PFUNMSG)GetProcAddress(hMoudle, "MsgBox");

      pFunMsg("Hello First Dll!");

      return 0;

}

编译、链接、并运行会产生如下结果:


原因是该工程下还没有firstDLL.dll文件,我们把该文件拷到新添加的工程目录下,如下:


再重新链接、运行后可以看到结果:


此时,我们的第一个DLL调用程序就成功了。是不是迫不及待想试一试了呢。

源码可在以下地址中获得:

http://pan.baidu.com/s/1b1xH2A




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值