DllMain函數

      Windows在加載DLL的時候,須要一個入口函數,就如同控制檯或DOS程序須要main函數、WIN32程序須要WinMain函數同樣。在前面的 例子中,DLL並無提供DllMain函數,應用工程也能成功引用DLL,這是由於Windows在找不到DllMain的時候,系統會從其它運行庫中 引入一個不作任何操做的缺省DllMain函數版本,並不意味着DLL能夠放棄DllMain函數。
根據編寫規範,Windows必 須查找並執行DLL裏的DllMain函數做爲加載DLL的依據,它使得DLL得以保留在內存裏。這個函數並不屬於導出函數,而是DLL的內部函數。這意 味着不能直接在應用工程中引用DllMain函數,DllMain是自動被調用的。函數

      咱們來看一個DllMain函數的例子 :線程

     BOOL APIENTRY DllMain( HANDLE hModule,
     DWORD ul_reason_for_call,
     LPVOID lpReserved進程

     )
     {
           switch (ul_reason_for_call)
          {
                    case DLL_PROCESS_ATTACH:
                             printf("\nprocess attach of dll");
                             break;
                    case DLL_THREAD_ATTACH:
                             printf("\nthread attach of dll");
                             break;
                    case DLL_THREAD_DETACH:
                            printf("\nthread detach of dll");
                            break;
                   case DLL_PROCESS_DETACH:
                           printf("\nprocess detach of dll");
                           break;
            }
            return TRUE;
}內存

      DllMain函數在DLL被加載和卸載時被調用,在單個線程啓動和終止時,DLLMain函數也被調用,ul_reason_for_call指明瞭被 調用的緣由。緣由共有4種,即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和THREAD_DETACH, 以switch語句列出。
來仔細解讀一下DllMain的函數頭BOOL APIENTRY DllMain( HANDLE hModule, WORD ul_reason_for_call, LPVOID lpReserved )。
APIENTRY被定義爲 __stdcall,它意味着這個函數以標準Pascal的方式進行調用,也就是WINAPI方式;
進程中的每一個DLL模塊被全局惟 一的32字節的HINSTANCE句柄標識,只有在特定的進程內部有效,句柄表明了DLL模塊在進程虛擬空間中的起始地址。在Win32 中,HINSTANCE和HMODULE的值是相同的,這兩種類型能夠替換使用,這就是函數參數hModule的來歷。it

        執行下列代碼:thread

        hDll = LoadLibrary("..\\Debug\\dllTest.dll");
        if (hDll != NULL)引用

        {
                addFun = (lpAddFun)GetProcAddress(hDll, MAKEINTRESOURCE(1));
                //MAKEINTRESOURCE 直接使用導出文件中的序號
               if (addFun != NULL)
               {
                       int result = addFun(2, 3);
                       printf("\ncall add in dll:%d", result);
               }
              FreeLibrary(hDll);bug

         }
咱們看到輸出順序爲:
process attach of dll
call add in dll:5
process detach of dll
這一輸出順序驗證了DllMain被調用的時機。
代碼中的GetProcAddress ( hDll, MAKEINTRESOURCE ( 1 ) )值得留意,它直接經過.def文件中爲add函數指定的順序號訪問add函數,具體體如今MAKEINTRESOURCE ( 1 ),MAKEINTRESOURCE是一個經過序號獲取函數名的宏,定義爲(節選自winuser.h):程序

       #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))
       #define MAKEINTRESOURCEW(i) (LPWSTR)((DWORD)((WORD)(i)))
       #ifdef UNICODE
              #define MAKEINTRESOURCE MAKEINTRESOURCEW
       #else
              #define MAKEINTRESOURCE MAKEINTRESOURCEAcall

相關文章
相關標籤/搜索