博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【windows核心编程】DLL相关(1)
阅读量:5264 次
发布时间:2019-06-14

本文共 2503 字,大约阅读时间需要 8 分钟。

 

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("\r\n***********B Dll DLL_PROCESS_ATTACH ***********\r\n"));        break;        //当该DLL已经被加载到进程地址空间后,当有新【线程创建】的时候,新创建的线程先执行此段代码        //然后再去执行线程本身的代码        //不管有几个DLL,每个DLL的此处代码都会被新线程执行    case DLL_THREAD_ATTACH:        OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_ATTACH ***********\r\n"));        break;        //当该DLL已经被加载到进程地址空间后,当有【线程结束】的时候,该线程结束之前会调用此处代码        //然后才返回        //不管有几个DLL,每个DLL的此处代码都会被执行    case DLL_THREAD_DETACH:        OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_DETACH *********** \r\n"));        break;        //只有在该DLL从内存中卸载的时候才会被调用一次     case  DLL_PROCESS_DETACH:        OutputDebugString(TEXT("\r\n***********B Dll DLL_PROCESS_DETACH ***********\r\n"));        break;    }#endif    return TRUE;}

 

 

demo

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

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

//加载DLLvoid 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("\r\n&&&&&&&&&&&&&&&&&&线程被创建&&&&&&&&&&&&&&&&&\r\n"));#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通知被调用一次。

 

 

转载于:https://www.cnblogs.com/cuish/p/3755893.html

你可能感兴趣的文章
2019春 软件工程实践 助教总结
查看>>
Zerver是一个C#开发的Nginx+PHP+Mysql+memcached+redis绿色集成开发环境
查看>>
多线程实现资源共享的问题学习与总结
查看>>
java实现哈弗曼树
查看>>
程序的静态链接,动态链接和装载 (补充)
查看>>
关于本博客说明
查看>>
线程androidAndroid ConditionVariable的用法
查看>>
转载:ASP.NET Core 在 JSON 文件中配置依赖注入
查看>>
代码变量、函数命名神奇网站
查看>>
redis cli命令
查看>>
Problem B: 占点游戏
查看>>
python常用模块之sys, os, random
查看>>
HDU 2548 A strange lift
查看>>
Linux服务器在外地,如何用eclipse连接hdfs
查看>>
react双组件传值和传参
查看>>
[Kaggle] Sentiment Analysis on Movie Reviews
查看>>
价值观
查看>>
mongodb命令----批量更改文档字段名
查看>>
MacOS copy图标shell脚本
查看>>
国外常见互联网盈利创新模式
查看>>