分类:
2010-12-08 18:16:54
2)扩展DLL的模块状态
7.3.1节指出扩展DLL的实现必须遵循五条规则,为此,首先在扩展DLL实现文件里头,定义AFX_EXTENSION_MODULE类型的静态扩展模块变量,然后在DllMain入口函数里头使用AfxInitExtension初始化扩展模块变量,并且实现和输出一个初始化函数供扩展DLL的使用者调用。
使用者必须具备一个CWinApp对象,通常在它的InitInstance函数中调用扩展DLL提供的初始化函数。
一般用以下的几段代码完成上述任务。首先是扩展模块变量的定义和初始化:
static AFX_EXTENSION_MODULE extensionDLL;
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(extensionDLL,hInstance))
return 0;
……
}
}
然后是扩展DLL的初始化函数,假定初始化函数命名为InitMyDll,InitMyDll被定义为“C”链接的全局函数,并且被输出。
// wire up this DLL into the resource chain
extern “C” void WINAPI InitMyDll()
{
CDynLinkLibrary* pDLL = new
CDynLinkLibrary(extensionDLL, TRUE);
ASSERT(pDLL != NULL);
...
}
最后是调用者的处理,假定在应用程序对象的InitInstance函数中调用初始化函数:
BOOL CMyApp::InitInstance()
{
InitMyMyDll();
…
}
上述这些代码只有在动态链接到MFC DLL时才有用。下面,对这些代码进行分析和解释
_AFX_EXTENSION_MODULE
在分析代码之前,先讨论描述扩展模块状态的_AFX_EXTENSION_MODULE类。_AFX_EXTENSION_MODULE没有基类,其定义如下:
struct AFX_EXTENSION_MODULE
{
BOOL bInitialized;
HMODULE hModule;
HMODULE hResource;
CRuntimeClass* pFirstSharedClass;
COleObjectFactory* pFirstSharedFactory;
};
其中:
第一个域表示该结构变量是否已经被初始化了;
第二个域用来保存扩展DLL的模块句柄;
第三个域用来保存扩展DLL的资源句柄;
第四个域用来保存扩展DLL要输出的CRuntimeClass类;
第五个域用来保存扩展DLL的OLE Factory。
该结构用来描述一个扩展DLL的模块状态信息,每一个扩展DLL都要定义一个该类型的静态变量,例如extensionDLL。
在DllMain中,调用AfxInitExtensionModule函数来初始化本DLL的静态变量该变量(扩展模块状态),如extensionDLL。函数AfxInitExtensionModule原型如下:
BOOL AFXAPI AfxInitExtensionModule(
AFX_EXTENSION_MODULE& state, HMODULE hModule)
其中:
参数1是DllMain传递给它的扩展DLL的模块状态,如extensionDLL;
参数2是DllMain传递给它的模块句柄。
AfxInitExtensionModule函数主要作以下事情:
(1)把扩展DLL模块的模块句柄hModule、资源句柄hModule分别保存到参数state的成员变量hModule、hResource中;
(2)把当前模块状态的m_classList列表的头保存到state的成员变量pFirstSharedClass中,m_classInit的头设置为模块状态的m_pClassInit。在扩展DLL模块进入DllMain之前,如果该扩展模块构造了静态AFX_CLASSINIT对象,则在初始化时把有关CRuntimeClass信息保存在当前模块状态(注意不是扩展DLL模块,而是应用程序模块)的m_classList列表中。因此,扩展DLL模块初始化的CRuntimeClass信息从模块状态的m_classList中转存到扩展模块状态state的pFirstSharedClass中,模块状态的m_classInit恢复被该DLL改变前的状态。
关于CRuntimeclass信息和AFX_CLASSINIT对象的构造,在3.3.1节曾经讨论过。一个扩展DLL在初始化时,如果需要输出它的CRuntimeClass对象,就可以使用相应的CRuntimeClass对象定义一个静态的AFX_CLASSINIT对象,而不一定要使用IMPLEMENT_SERIAL宏。当然,可以序列化的类必定导致可以输出的CRuntimeClass对象。
(3)若支持OLE的话,把当前模块状态的m_factoryList的头保存到state的成员变量pFirstSharedFactory中。m_factoryList的头设置为模块状态的m_m_pFactoryInit。
(4)这样,经过初始化之后,扩展DLL模块包含了扩展DLL的模块句柄、资源句柄、本模块初始化的CRuntimeClass类等等。
扩展DLL的初始化函数将使用扩展模块状态信息。下面,讨论初始化函数的作用。