您的位置:首页 > 其它

DLL的简单实现及调用

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

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

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

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

BOOL
APIENTRY DllMain(

HMODULE
hModule,

DWORD
ul_reason_for_call,

LPVOID
lpReserved

);

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: