動態鏈接到 MFC 的 規則 DLL 應用程序裡頭的輸出函數可以被任意 Win32 程序使用,包括使用 MFC 的應用程序。但是,所有從 DLL 輸出的函數應該以如下語句開始:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
此語句用來正確地切換 MFC 模塊狀態。
Regular DLL能夠被所有支持 DLL 技術的語言所編寫的應用程序所調用。在這種動態連接庫中,它必須有一個從 CWinApp 繼承下來的類,DLLMain 函數被 MFC 所提供,不用自己顯式的寫出來。
Extension DLL:用來實現從 MFC 所繼承下來的類的重新利用,也就是說,用這種類型的動態連接庫,可以用來輸出一個從 MFC 所繼承下來的類。它輸出的函數僅可以被使用 MFC 且動態鏈接到 MFC 的應用程序使用。可以從 MFC 繼承你所想要的、更適於你自己用的類,並把它提供給你的應用程序。你也可隨意的給你的應用程序提供 MFC 或 MFC 繼承類的對象指針。Extension DLL使用 MFC 的動態連接版本所創建的,並且它只被用 MFC 類庫所編寫的應用程序所調用。Extension DLLs 和 Regular DLLs 不一樣,它沒有從 CWinApp 繼承而來的類的對象,所以,你必須為自己 DLLMain 函數添加初始化代碼和結束代碼。
和規則 DLL 相比,有以下不同:
1、它沒有從 CWinApp 派生的對象; 2、它必須有一個 DLLMain 函數; 3、DLLMain 調用 AfxInitExtensionModule 函數,必須檢查該函數的返回值,如果返回0,DLLMmain 也返回 0; 4、如果它希望輸出 CRuntimeClass 類型的對象或者資源,則需要提供一個初始化函數來創建一個 CDynLinkLibrary 對象。並且,有必要把初始化函數輸出; 5、使用擴展 DLL 的 MFC 應用程序必須有一個從 CWinApp 派生的類,而且,一般在InitInstance 裡調用擴展 DLL 的初始化函數。
1、每一個 DLL 必須有一個入口點,DLLMain 是一個缺省的入口函數。DLLMain 負責初始化和結束工作,每當一個新的進程或者該進程的新的線程訪問 DLL 時,或者訪問 DLL 的每一個進程或者線程不再使用DLL或者結束時,都會調用 DLLMain。但是,使用 TerminateProcess 或 TerminateThread 結束進程或者線程,不會調用 DLLMain。
DLLMain的函數原型:
BOOL APIENTRY DLLMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: ....... case DLL_THREAD_ATTACH: ....... case DLL_THREAD_DETACH: ....... case DLL_PROCESS_DETACH: ....... return TRUE; } }
參數:
hMoudle:是動態庫被調用時所傳遞來的一個指向自己的句柄(實際上,它是指向_DGROUP段的一個選擇符); ul_reason_for_call:是一個說明動態庫被調原因的標志。當進程或線程裝入或卸載動態連接庫的時候,操作系統調用入口函數,並說明動態連接庫被調用的原因。它所有的可能值為: DLL_PROCESS_ATTACH: 進程被調用; DLL_THREAD_ATTACH: 線程被調用; DLL_PROCESS_DETACH: 進程被停止; DLL_THREAD_DETACH: 線程被停止;
lpReserved:是一個被系統所保留的參數;
2、_DLLMainCRTStartup
為了使用 "C" 運行庫 (CRT,C Run time Library) 的 DLL 版本(多線程),一個 DLL 應用程序必須指定 _DLLMainCRTStartup 為入口函數,DLL 的初始化函數必須是 DLLMain。 _DLLMainCRTStartup 完成以下任務:當進程或線程捆綁(Attach) 到 DLL 時為 "C" 運行時的數據 (C Runtime Data) 分配空間和初始化並且構造全局 "C++"對象,當進程或者線程終止使用DLL(Detach) 時,清理 C Runtime Data 並且銷毀全局 "C++" 對象。它還調用 DLLMain 和 RawDLLMain 函數。 RawDLLMain 在 DLL 應用程序動態鏈接到 MFC DLL 時被需要,但它是靜態鏈接到 DLL 應用程序的。在講述狀態管理時解釋其原因。