dll文件详解文档格式.docx
《dll文件详解文档格式.docx》由会员分享,可在线阅读,更多相关《dll文件详解文档格式.docx(10页珍藏版)》请在冰豆网上搜索。
MFC扩展DLL具有下列功能和要求:
1客户端可执行文件必须是用定义的_AFXDLL编译的MFC应用程序。
2扩展DLL也可由动态链接到MFC的规则DLL使用。
3扩展DLL应该用定义的_AFXEXT编译。
这将强制同时定义_AFXDLL,并确保从MFC头文件中拉入正确的声明。
它也确保了在生成DLL时将AFX_EXT_CLASS定义为__declspec(dllexport),这在使用此宏声明扩展DLL中的类时是必要的。
4扩展DLL不应实例化从CWinApp派生的类,而应依赖客户端应用程序(或DLL)提供此对象。
5但扩展DLL应提供DllMain函数,并在那里执行任何必需的初始化。
扩展DLL是使用MFC动态链接库版本(也称作共享MFC版本)生成的。
只有用共享MFC版本生成的MFC可执行文件
(应用程序或规则DLL)才能使用扩展DLL。
客户端应用程序和扩展DLL必须使用相同版本的MFCx0.dll。
使用扩展DLL,可以从MFC派生新的自定义类,然后将此“扩展”版本的MFC提供给调用DLL的应用程序。
具体执行时,主要是资源的管理:
mfc扩展dll会把当前dll的句柄加入一个全局资源句柄列表。
而普通的dll则不会。
即使支持mfc也不会,这样你每次用mfc类创建资源的时候要多写几行代码。
但你用在mfc扩展dll用win32来访问资源也需要多写代码。
==============================================================
扩展DLL可以导出类
扩展DLL服务器方的类定义:
classAFX_CLASS_EXPORT到出类名:
public基类名
{
............
}
扩展DLL客户方的类声明头文件:
#pragmacomment(lib,"
lib文件名"
)
classAFX_CLASS_IMPORT到出类名:
public基类名
常规DLL可以导出标准C语言函数
常规DLL服务器方的函数定义:
//
头文件中函数声明
extern"
C"
__declspec(dllexport)
返回值函数名
(
形式参数声明
;
//源文件中函数实现
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
//
第一条语句
..............
}
在def模块文件中声明函数序号
EXPORTS导出函数名@序号数字
常规DLL客户方的隐式函数声明头文件:
======================================================
另外,所有的动态链接库都有两种链接方式:
隐式调用和显示调用。
隐式调用
编译程序时需要头文件、lib文件,运行时需要DLL文件,并且运行过程中DLL文件一直被占用。
显式调用
编译时什么都不需要,在需要使用DLL中的函数时,通过LoadLibrary()和FindProcAdress()这两个API调用。
只需要一个DLL文件即可,而且在需要使用的时候DLL才被占用,使用完毕即被解除占用。
DLL中有哪些函数可以通过Depends工具查询。
==================================================================
Part2
如何制作生成dll文件?
一.Win32动态链接库
1.制作的步骤:
(1)新建WIN32Dynamic-linkLibrary工程,工程名为MyDll,选择AsimpleDLLproject类型。
(2)MyDll.h的内容如下:
以下是引用片段:
extern"
_declspec(dllexport)intsum(inta,intb);
//本文所有的例子只有一个sum即加法函数。
(3)MyDll.cpp的内容如下:
#include"
stdafx.h"
windows.h"
MyDll.h"
BOOLAPIENTRYDllMain(
HANDLEhModule,
DWORDul_reason_for_call,
LPVOIDlpReserved
)
{
returnTRUE;
}
_declspec(dllexport)intsum(inta,intb)
returna+b;
(4)编译之后产生了MyDll.lib与MyDll.dll两个文件。
2.使用方法:
(1).隐式调用法:
将MyDll.lib和MyDll.h拷贝到需要应用该DLL的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中添加如下几行:
#pragmacomment(lib,"
MyDll"
);
(2).显示调用法:
将MyDll.lib和MyDll.h拷贝到需要应用该DLL的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中包含头文件,如:
同时还需要在Project->
Setting->
Link->
Object/librarymodules的框中增加MyDll.lib这个库。
二.MFC动态链接库
(1)新建MFCAppWizard(dll)工程,工程名为MFCDll,选择RegularDLLusingsharedMFCDLL类型。
(2)在生成的MFCDll.cpp文件后面增加下面几行:
intsum(inta,intb)
(3)在生成的MFCDll.def文件后面增加如下:
sum@1;
表示第一个函数是sum
(4)编译后会产生两个文件MFCDll.lib,MFCDll.dll
2.使用方法
(1)隐式调用法:
将MFCDll.lib拷贝到需要应用该DLL的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中添加如下几行:
//注意这里没有在MFCDll.h中声明函数,所以不能直接包含MFCDll.h来声明函数。
MFCDll"
intsum(inta,intb);
//当然如果你的DLL中有很多函数,那可以另外写个MFCDll.h,包含所有的函数声明,然后直接将头文件包含进去
(2)显示调用法:
与Win32的调用方法一样,不需要#pragmacomment(lib,"
,但是需要在Project->
Object/librarymodules的框中增加MFCDll.lib这个库。
==========================================================
另一个例子:
具体在写DLL文件头文件中一般如此:
#ifdefDLL_EXPORT
#defineDECLDIR__declspec(dllexport)
#else
#defineDECLDIR__declspec(dllimport)
#endif
{
DECLDIRvoidalert();
}
这样使得在定义了DLL_EXPORT的环境下,头文件中,函数为导出;
相反为导入。
于是,我们可以使用同一个头文件。
此时是在写DLL,还是在使用DLL,只需要通过这个开关来告诉编译器就可以了。
实现cpp中一般这么写:
#include"
#defineDLL_EXPORT
MyHead.h"
DECLDIRvoidalert()
MessageBoxA(NULL,"
Hello,World!
"
0,0);
在引用头文件前定义DLL_EXPORT,告诉编译器此时这些函数需要导出。
MyTestDLL.lib"
)
int_tmain(intargc,_TCHAR*argv[])
alert();
//直接调用
return0;
由于我们没有定义DLL_EXPORT,那么头文件中的函数就会被从DLL中导入。
#include<
windows.h>
typedefvoid(*alert)();
alertfunc=NULL;
HINSTANCEh=LoadLibraryA("
MyTestDLL.dll"
if(h)
func=(alert)GetProcAddress(h,"
alert"
if(NULL!
=func)
func();
FreeLibrary(h);
首先定义函数指针类型,然后实例化一个该类型的函数。
最后调用即可。