分类:
2010-12-08 18:17:45
扩展DLL的初始化函数
在初始化函数InitMyDll中,创建了一个动态的CDynLinkLibrary对象,并把对象指针保存在pDLL中。CDynLinkLibrary类从CCmdTarget派生,定义如下:
class CDynLinkLibrary : public CCmdTarget
{
DECLARE_DYNAMIC(CDynLinkLibrary)
public:
// Constructor
CDynLinkLibrary(AFX_EXTENSION_MODULE& state,
BOOL bSystem = FALSE);
// Attributes
HMODULE m_hModule;
HMODULE m_hResource; // for shared resources
CTypedSimpleList
#ifndef _AFX_NO_OLE_SUPPORT
CTypedSimpleList
#endif
BOOL m_bSystem; // TRUE only for MFC DLLs
// Implementation
public:
CDynLinkLibrary* m_pNextDLL; // simple singly linked list
virtual ~CDynLinkLibrary();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif //_DEBUG
};
CDynLinkLibrary的结构和AFX_EXTENSION_MODULE有一定的相似性,存在对应关系。
CDynLinkLibrary构造函数的第一个参数就是经过AfxInitExtensionModule初始化后的扩展DLL的模块状态,如extensionDLL,第二个参数表示该DLL模块是否是系统模块。
创建CDynLinkLibrary对象导致CCmdTarget和CDynLinkLibrary类的构造函数被调用。CCmdTarget的构造函数将获取模块状态并且保存在成员变量m_pModuleState中。CDynLinkLibrary的构造函数完成以下动作:
构造列表m_classList和m_factoryList;
把参数state的域hModule、hResource复制到对应的成员变量m_hModule、m_hResource中;
把state的pFirstSharedClass、pFirstSharedFactory分别插入到m_classList列表、m_factoryList列表的表头;
把参数2的值赋值给成员变量m_bSystem中;
至此,CDynLinkLibrary对象已经构造完毕。之后,CDynLinkLibrary构造函数把CDynLinkLibrary对象自身添加到当前模块状态(调用扩展DLL的应用程序模块或者规则DLL模块)的CDynLinkLibrary列表m_libraryList的表头。为了防止多个线程修改模块状态的m_libraryList,访问m_libraryList时使用了同步机制。
这样,调用模块执行完扩展模块的初始化函数之后,就把该扩展DLL的资源、CRuntimeClass类、OLE Factory等链接到调用者的模块状态中,形成一个链表。图9-8表明了这种关系链。
综合以上分析,可以知道:
扩展DLL的模块仅仅在该DLL调用DllMain期间和调用初始化函数期间被使用,在这些初始化完毕之后,扩展DLL模块被链接到当前调用模块的模块状态中,因此它所包含的资源信息等也就被链接到调用扩展DLL的应用程序或者规则DLL的模块状态中了。扩展DLL扩展了调用者的资源等,这是“扩展DLL”得名的原因之一。
也正因为扩展DLL没有自己的模块状态(指AFX_MODULE_STATE对象,扩展DLL模块状态不是),而且必须由有模块状态的模块来使用,所以只有动态链接到MFC的应用程序或者规则DLL才可以使用扩展DLL模块的输出函数或者输出类。