nginx 调用dll_使用DLL中的资源
我很早的时候写过一篇MFC中CDialog与其对话框资源的绑定,但这几天在MFC DLL上做了一些工作后发现当时的理解实在肤浅。说不定过了几年再回头看看目前这篇文章,又觉得本文也是鬼话连篇了吧,哈哈。
使用DLL中的资源面临的一个主要问题是,DLL和EXE中都有资源集,但是程序在运行态到底会去哪个资源集中找常常令我们疑惑。
考虑如下的经典情况:
在新建MFC DLL工程时选中Regular DLL using shared MFC DLL选项,新建一个与MFC自身DLL共享的DLL。在新DLL中新建一个ID名为IDD_DLLDIALOG的对话框资源。在这个DLL中导出一个ShowDialog()函数,内容如下:
1
extern "C" void Show Dialog()
2
{
3
CDialog dlg(IDD_DLLDIALOG);
4
dlg.DoModal();
5
}
新建一个MFC的EXE工程,导入刚刚新建的DLL工程的lib和dll,将OK按钮的响应函数设置为: ShowDialog(); 编译链接通过后,我们运行起程序来会发现点击OK按钮后什么反应都没有!怎么会这样?我们不是明明在DLL里设定好了IDD_DLLDIALOG吗?请大家注意“在新建MFC DLL工程时选中Regular DLL using shared MFC DLL”这句话,如果我们当时选的是“Regular DLL with MFC statically linked”又会是什么情况呢?又能正常显示了!
使用静态连接的方式访问MFC库DLL,会把MFC库DLL与工程本身一起打包,而共享的方式则会在运行时去系统路径中动态加载MFC库DLL。我们可以这么理解以上的现象:如果新建的DLL使用共享的方式访问库DLL,当EXE程序运行时,实际上有两套上下文系统在运作,而静态连接则只有一套上下文系统了,因此在静态连接时会需要进行模块状态的切换。
当我们新建的是共享方式访问 库DLL的DLL时,要解决上述问题比较通用的做法是在ShowDialog函数里面加上一句AFX_MANAGE_STATE(AfxGetStaticModuleState());
AfxGetStaticModuleState()的原型为:
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState( );
即当前模块的ModuleState指针。
AFX_MANAGE_STATE宏则会以传入的指针为参数去在栈上新建一个类,此类会做哪些事相信聪明的你也能猜到了.没错,它会在构造函数中存下当前的ThreadState所指向的ModuleState指针,再将传入的指针指定为当前ThreadState所指向的指针。等到这个类的实例被析构是,又将其改回去。
令外一种方法是使用AfxGetResourceHander()配合AfxSetResourceHander(HINSTANCE)了(这也正是我在MFC中CDialog与其对话框资源的绑定中介绍的方法)。
如果我们不想在EXE中通过间接的调用DLL导出的ShowDialog(),而是直接想在EXE的OnBnClickedOk()中生成一个使用DLL中对话框资源的对话框呢?这时AFX_MANAGE_STATE(AfxGetStaticModuleState())就派不上用场了(因这它是用在DLL工程中的)。最好的办法是用AfxSetResourceHander(HINSTANCE)配合GetModuleHandle(LPCTSTR)。
GetModuleHandle(LPCTSTR str)将会根据传入的字符串得到相应的模块句柄。注意,EXE和DLL都可以被看作是模块。当传入为空(NULL)时,将得到当前进程(EXE)的HINSTANCE句柄。使用GetModuleHandle要保证相应的dll已经被加载,也许你会说这个条件不是废话么,但是这确实是很容易犯错的地方。
如果是用静态加载DLL的方式(即直接把生成的那个.lib文件导入),而之前又从未调用过这个dll中的任何函数或变量的话,GetModuleHandle只会得到一个空值。因为系统会直到有某个语句调用过dll里面的东西时才会将dll真正加载。
例如:
1
void CUseDllDlg::OnBnClickedOk()
2
{
3
HINSTANCE temp = AfxGetResourceHandle();
4
AfxSetResourceHandle(GetModuleHandle(_T("RegDll")));
5
CDialog dlg(4000);
6
dlg.DoModal();
7
AfxSetResourceHandle(temp);
8
}
上面的这份代码运行时会报错,因为AfxSetResourceHandle在检查入参时发现了个空值。而下面的代码则不会有问题:
1
void CUseDllDlg::OnBnClickedOk()
2
{
3
ASSERT(TestOnly() == 1);
4
HINSTANCE temp = AfxGetResourceHandle();
5
AfxSetResourceHandle(GetModuleHandle(_T("RegDll")));
6
CDialog dlg(4000);
7
dlg.DoModal();
8
AfxSetResourceHandle(temp);
9
}
其中TestOnly也是从RegDll中导出的函数,它什么都不做,只是返回一个1。我们使用它只是为了把RegDll加载进来。当然了,如果我们直接使用动态加载的方法,像下面这样直接LoadLibrary那更是没有问题了。
1
void CUseDllDlg::OnBnClickedOk()
2
{
3
HMODULE hm= LoadLibrary(_T("..//Debug//RegDll.dll"));
4
HINSTANCE temp = AfxGetResourceHandle();
5
AfxSetResourceHandle(GetModuleHandle(_T("RegDll")));
6
CDialog dlg(4000);
7
dlg.DoModal();
8
AfxSetResourceHandle(temp);
9
}
不过眼尖的读者可能会立即发现其实在上面这种情况下使用GetModuleHandle不是最好的选择。因为直接来个AfxSetResourceHandle(hm)就可解决问题了。
nginx 调用dll_使用DLL中的资源相关推荐
- C++ Builder创建和调用dll中的资源
程序开发中经常会用到一些图标.图片.光标.声音等,我们称它们为资源(Resource).当多个窗口用到同样的资源时,可以将这些公共的资源放到一个dll文件里调用,这样,由于定位资源比在磁盘中定位文件花 ...
- 【Demo 0121】纯资源DLL中提取资源
DLL 用途非常广泛,正如前几节中所有的,DLL可以封装函数.变量以及类. 而今天我们继续扩展DLL的用途,如何实现一个纯资源的DLL, 这个DLL没有入口也就是没有DllMain函数在VS中设置无入 ...
- 学习使用资源文件[11] - DLL 中的资源文件
本例将把一张 bmp 图片, 以资源文件的方式嵌入 dll, 然后再调用. 第一步: 建一个 DLL 工程, 如图: 然后保存, 我这里使用的名称都是默认的. 第二步: 建一个资源原文件, 如图: 编 ...
- MFC中制作Dll中带对话框资源的动态库
Data:2019/10/23 这篇文章本来是17年写的,现在对这边文章进行细化.更新的是有一些晚了些 想要在MFC中的dll里面添加对话框资源,首先必须的条件是,当前的dll库类型必须是可扩展的DL ...
- ASP.NET 2.0 中的资源与本地化
转自MSDN 下载本文的代码:BasicInstincts2006_08.exe (878KB) 本页内容 控制页面级别的区域性设置 使用配置文件跟踪语言首选项 ASP.NET 2.0 中的资源文件 ...
- 如何使用动态链接库中的资源
近来在论坛上很有多帖子问到如何使用DLL中的资源(包括对话框,图标等)的问题,现在笔者就来就此问题谈谈,包含在DLL内部使用资源,DLL中使用其它DLL中的资源和在应用程序中使用资源. 我们先以图标为 ...
- Win32 DLL和MFC DLL 中封装对话框
Win32 DLL和MFC DLL 中封装对话框 分类: 挂挂2007-07-02 12:36 3344人阅读 评论(1) 收藏 举报 现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是 ...
- 如何查看exe或dll调用了什么dll
[转载]如何查看exe或dll调用了什么dll呢 已有 19410 次阅读 2014-4-17 21:08|系统分类:科研笔记|文章来源:转载 Dependency Walker使用说明 在Windo ...
- Java通过JNI调用C++动态链接库dll,并打在jar包内 ——JNA-JNI(一)
Java通过JNI调用C++动态链接库dll,并打在jar包内--JNA-JNI(一) 系列文章: Java通过JNI调用C++动态链接库dll,并打在jar包内 --JNA-JNI(一) Java使 ...
最新文章
- mongodb中简单的根据时间过滤进行查询
- vat可以退税吗_【涨知识】企业对外投资可以申请出口退税吗?
- git配置取消代理_「高手」如何优雅的解决 git 超时
- Spring boot中的Http压缩配置
- kvm初体验之八:调整vm的vcpu, memory, disk大小
- 流水灯c语言代码大全,单片机闪烁灯流水灯汇编代码大全
- 影楼——修图基本知识
- 正则表达式匹配非负数字
- 论文排版——Latex页眉页脚设定(中英都可以适用)
- 2018_2_3_Boolean Expressions_栈_模拟
- 【关于Log4j2】
- 数值模拟使用matlab实现案例
- MySQL学习笔记(1)——高可用组复制
- Java实现远程主机唤醒 (WOL)
- NEO4J-链路预测算法03-优先链接算法(Preferential Attachment)应用场景简介
- 使用Rational Performance Tester实现DB2 性能测试和监控
- arcgis直方图导出地图_利用Arcgis地图工具自动输出报告地图图纸
- 携职教育:初级会计考试明明不难,为什么通过率这么低?
- 从外部的js文件中获取ASPX页面的控件ClientID(get control reference from external javascript)...
- 学Linux网络管理有它就够了
热门文章
- 从链接上获取参数值, location.href上获取参数
- 主数据处理链碰到空数据节点不在继续执行的问题解决方案
- 关于移动端布局和pc端写法
- 详细了解文档对象模型(DOM)
- JS-内置对象内置构造函数事件-拖拽轮播图无缝滚动
- Iphone如何应对华为鸿蒙系统,鸿蒙2.0向iOS看齐 系统解决了 芯片怎么办?
- python yield: send, close, throw
- Matrix: android 中的Matrix (android.graphics.Matrix) (转)
- 使用svn进行本地代码管理
- CSS-Position