DLL相关知识总结
2008-08-03 01:01
281 查看
一、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文件引用计数
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文件引用计数
相关文章推荐
- 关于win32 dll 的相关知识总结
- dll 学习相关知识总结
- WinForm开发,窗体显示和窗体传值相关知识总结
- Linux相关知识总结
- RTP协议相关知识总结
- Android——Broadcast Receive 相关知识总结贴
- 2012-03-20:并行计算相关知识总结
- DataGrid相关知识总结(收集)
- ios 方面总结的相关知识(1)
- Ajax相关技术知识总结
- 抓包工具 Fiddler 相关知识总结
- HTML相关知识总结一于2015-05-04记录
- 黑马程序员_事件、反射、网络相关知识总结
- c#基础知识4:dll相关
- JVM相关知识总结整理
- DLL相关知识
- View相关知识学习总结
- JAVA相关基础知识总结(连载)-5
- JAVA相关基础知识总结(连载)-7
- Unity脚本-移动相关知识总结