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的来历。

        执行下列代码:

        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);

         }
我们看到输出顺序为:
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 MAKEINTRESOURCEA

你可能感兴趣的:(DllMain函数)