DLL相关知识总结

本文总结了DLL的关键知识点,包括DllMain函数的作用、.def文件的使用以确保跨编译器调用一致性、C语言调用规则(stdcall)与PASCAL调用规则、DLL函数的导入导出以及静态加载与动态加载的区别和示例。通过这些内容,读者可以深入理解DLL的工作原理和使用技巧。
 

一、DllMain 函数的使用。

BOOL WINAPI DllMain(
HANDLE hinstDLL, //保存dll的句柄
DWORD dwReason,
LPVOID lpvReserved
);

DllMain函数是DLL文件中一个可选的函数,当Dll文件中的某个函数需要使用当前dll的句柄时,就可以调用这个函数,同时可以在这个函数中进行简单的业务处理(注意不要提供太复杂的处理)。

二、DLL模块定义文件(.def文件)的使用。

由于在Dll中定义并导出的函数将要在调用dll的程序中被调用,那么由于编译器对函数名字改编,不同编译器改编之后的结果可能不同,这样就给函数的调用带来麻烦。同时为了使Dll能够在不同的程序语言中调用,就要使用模块定义文件来规范函数的导出名字。

三、关于Dll中函数的调用规则:1.C语言调用规则(C、C++语言的默认调用规则) 2.标准调用规则_stdcall(也就是PASCAL调用规则)——一般为了使dll可以为多种语言服务使用_stacall调用规则。

四、Dll的函数导入和导出。

在dll的CPP文件中函数定义前应该加上extern "C" _declspec(dllexport) _stdcall来说明函数是要导出的,并采用标准调用约定。在.h文件中的函数声明前加上extern "C" _declspec(dllimport) 函数返回类型 _stdcall(因为这个头文件是要给调用dll的客户程序使用的,所以是dllimport).为了方便书写可以采用下面的写法:

dll1.h文件头

#ifdef DLL1_API
#else
#define DLL1_API extern "C" _declspec(dllimport)
#endif

DLL1_API int _stdcall add(int a,int b);

dll1.cpp文件头

#define DLL1_API extern "C" _declspec(dllexport)
#include "Dll1.h"

int _stdcall add(int a,int b) //这里不必在int前添加DLL_API了
{
return a+b;
}

注意:关键字extern "C" 不能应用到类和类的成员函数中,如果想导出类应该使用模块定义文件导出。

五、Dll的加载:

1.静态加载(又称隐式加载):采用.Lib文件,这种方法简单方便,容易掌握,需要dll的头文件。在客户程序启动时将所有要用到的dll加载到内存中,这样就带来一个问题,如果客户程序需要调用很多个dll,而每个dll中只是调用很少的函数,那么会造成资源的浪费,使程序变慢。——这时应使用动态加载来解决这个问题。

2.动态加载(又称显示加载):不需要dll的头文件。在客户程序启动后,需要调用dll文件的函数时,在用函数加载dll,这样的效率比较高。下面是调用名字为Dll3的dll中add函数的方法示例:

HINSTANCE hInst;
hInst=LoadLibrary("Dll3.dll"); //将dll3.dll加载到内存,同时增加对其的引用计数,并保存dll的实例句柄。
typedef int (_stdcall *ADDPROC)(int a,int b); //定义函数指针,通过GetProcAddress得到add函数的地址
ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");//找到add函数的入口地址并保存在指针Add中
if(!Add)
{
   MessageBox("获取函数地址失败!");
   return;
}
CString str;
str.Format("5+3=%d",Add(5,3));
MessageBox(str);
FreeLibrary(hInst);//减少对dll文件引用计数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值