zoukankan      html  css  js  c++  java
  • 【windows核心编程】DLL相关(1)

     

    DLL相关的东西

     

    1、DLL的加载方式

    隐式:

    #pragma comment(lib, "XX.lib");

    编译器去查找名为XX.dll的DLL,除了名字相同,该DLL和该LIB的GUID也相同。

     

    显式:

    HINSTANCE   hInst = LoadLibrary(TEXT("XX.dll"));

    if(NULL == hInst)  retrun;

     

    HINSTANCE hInst = LoadLibrary(TEXT("XX.dll"), NULL,   FLAGS);

    第三个参数为一些标志,详见核心编程。

     

    2、DLL的入口函数

    原型

    BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    );

    其中hModule为该DLL在当前进程地址空间中的位置,ul_reason_for_call为调用此函数的原因,lpReserved如果为显式加载则为0,如果为隐式加载则为非0。

    详细说一下ul_reason_for_call

    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
    #ifdef _DEBUG
    
        switch (ul_reason_for_call)
        {
            //只在该DLL第一次加载进地址空间的时候被调用一次
            //此后当该DLL被加载进不同进程的地址空间时让然不调用
            //当主调线程通过该reason调用DllMain函数时,主调线程不会收到DLL_THREAD_ATTACH通知
        case DLL_PROCESS_ATTACH:
            OutputDebugString(TEXT("
    ***********B Dll DLL_PROCESS_ATTACH ***********
    "));
            break;
    
            //当该DLL已经被加载到进程地址空间后,当有新【线程创建】的时候,新创建的线程先执行此段代码
            //然后再去执行线程本身的代码
            //不管有几个DLL,每个DLL的此处代码都会被新线程执行
        case DLL_THREAD_ATTACH:
            OutputDebugString(TEXT("
    ***********B Dll DLL_THREAD_ATTACH ***********
    "));
            break;
    
            //当该DLL已经被加载到进程地址空间后,当有【线程结束】的时候,该线程结束之前会调用此处代码
            //然后才返回
            //不管有几个DLL,每个DLL的此处代码都会被执行
        case DLL_THREAD_DETACH:
            OutputDebugString(TEXT("
    ***********B Dll DLL_THREAD_DETACH *********** 
    "));
            break;
    
            //只有在该DLL从内存中卸载的时候才会被调用一次 
        case  DLL_PROCESS_DETACH:
            OutputDebugString(TEXT("
    ***********B Dll DLL_PROCESS_DETACH ***********
    "));
            break;
        }
    
    #endif
    
        return TRUE;
    }

     

     

    demo

    有两个DLL, ADll.dll 和 BDll.dll

    在程序中加载这个两个DLL, 然后创建一个新线程,看输出

    //加载DLL
    void CUseABDllDlg::OnBnClickedBtnLoadlib()
    {
        HINSTANCE hInstA = LoadLibrary(_T("ADll.dll"));
        HINSTANCE HIntB = LoadLibrary(_T("BDll.dll"));
        if (NULL == hInstA || NULL == HIntB)
        {
            AfxMessageBox(_T("加载DLL失败"));
            return;
        }  
    }
    
    //线程函数
    UINT WINAPI WorkThread(LPVOID lpParam)
    {
    #ifdef _DEBUG
        OutputDebugString(TEXT("
    &&&&&&&&&&&&&&&&&&线程被创建&&&&&&&&&&&&&&&&&
    "));
    #endif
    
        return 0U;
    }
    
    //创建线程
    void CUseABDllDlg::OnBnClickedButton2()
    {
        HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, WorkThread, NULL, 0, NULL);
        if (NULL == hThread || INVALID_HANDLE_VALUE == hThread)
        {
            AfxMessageBox(_T("创建线程失败"));
        }
    }

     

     

    输出

     

    结论:

    每创建一个新线程,当前进程地址空间中的DLL的DllMain函数都会通过DLL_THREAD_ATTACH通知被调用一次

    每结束一个线程,进程地址空间空的DLL的DllMain函数都会通过DLL_THREAD_DETACH通知被调用一次。

     

     

  • 相关阅读:
    JVM1
    JVM
    安卓权威编程指南 -笔记(19章 使用SoundPool播放音频)
    安卓权威编程指南 -笔记(18章 处理assets)
    安卓权威编程指南 挑战练习 16章
    安卓权威编程指南 -挑战练习 15章。
    安卓权威编程指南 挑战练习 13.8 用于RecyclerView的空视图
    安卓权威编程指南 挑战练习13.7-优化字符串资源显示
    关于List比较好玩的操作
    安卓权威编程指南 挑战练习13.6 14.8
  • 原文地址:https://www.cnblogs.com/cuish/p/3755893.html
Copyright © 2011-2022 走看看