动态链接库DLL
来源:互联网 发布:ambari源码 编辑:程序博客网 时间:2024/05/27 16:40
这是转载博客园的一篇文章,我进行了一下简单的整理
原文链接:http://www.cnblogs.com/lidabo/archive/2013/08/30/3291784.html。
我们先以图标为例说起(其它的资源与此图标的加载原理大致相同),我们要加载图标,一般是调用AfxGetApp()->LoadIcon(…);下面是CWinApp::LoadIcon的实现(afxwin2.inl):
_AFXWIN_INLINE HICON CWinApp::LoadIcon(LPCTSTR lpszResourceName) const{ return ::LoadIcon(AfxFindResourceHandle(lpszResourceName,RT_GROUP_ICON), lpszResourceName); }_AFXWIN_INLINE HICON CWinApp::LoadIcon(UINT nIDResource) const{ return ::LoadIcon(AfxFindResourceHandle(MAKEINTRESOURCE(nIDResource), RT_GROUP_ICON), MAKEINTRESOURCE(nIDResource)); }
可以看到CWinApp::LoadIcon实际上调用了API .LoadIcon,下面是API LoadIcon的原型:
HICON LoadIcon( HINSTANCE hInstance, LPCTSTR lpIconName);
hInstance
[in] Handle to an instance of the module whose executable file contains the icon to be loaded. This parameter must be NULL when a standard icon is being loaded.
hInstance是我们要加载ICON的模块实例,这个实例从何来,当然我们可以直接传入DLL的实例,对于通过LoadLibrary动态加载的DLL我们可以很容易的得到其句柄,但对于我们直接链接的DLL得到其句柄则要费一番周折。可以看到CWinApp::LoadIcon是通过AfxFindResouceHandle找到此句柄的。
下面是AfxFindResourceHandle的定义(afxwin.h):
#ifndef _AFXDLL#define AfxFindResourceHandle(lpszResource, lpszType) AfxGetResourceHandle()#elseHINSTANCE AFXAPI AfxFindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType);#endif
我们先讨论在静态链接库中使用MFC DLL的情况。可以看到,我们如果在静态库中使用MFC DLL的话(#ifndef _AFXDLL),实际上就是调用的AfxGetResourceHandle,
关于AfxGetResourceHandle,MSDN中的说明是:
AfxGetResourceHandle
This function accesses the application’s resources directly by using the HINSTANCE handle returned, for example, in calls to the Windows function FindResource.
HINSTANCE AfxGetResourceHandle( );
Return Value:An HINSTANCE handle where the default resources of the application are loaded.
我们只需将DLL的HINSTANCE传入AfxSetResouceHanle就行了。如何得到DLL的HINSTANCE呢,我们可以通过DLL声明一个接口HINSTANCE GetInstance获得,也可以通过EnumProcessMoudules找到(详细的过程见MSDN中EnumProcessModules的说明和示例)。
我们使用完DLL中的资源要使用EXE中的资源的资源怎么办呢?我们需要在使用完成后用AfxSetResource重新将资源模块的句柄设置为原来的值,如果来保证在资源使用完成后完成这一个工作呢,即使在使用过程中发生异常了,为此我们利C++类的构造和析构机制创建了这一类:
class CLocalResource {public: CLocalResource(HINSTANCE hInstance) { m_hInstOld=AfxGetInstanceHandle(); AfxSetInstanceHandle(hInstance); } virtual ~CLocalResource() { AfxSetInstanceHandle(m_hInstOld); }protected: HINSTANCE m_hInstOld;};
我们只需在使用DLL的资源之前构造一个CLocalInstance就行了.
void CXXXX::LoadResouceFromDLL(HINSTANCE hInst,UINT nResID,…){ CLocalResouce localRes(hInst); …}
下面来讨论在动态库中使用MFC DLL的情况(也就是定义了_AFXDLL的情况),
来看看AfxGetInstanceHandle ,AfxGetResourceHandle和AfxSetResouceHandle的实现(afxwin1.inl中):
_AFXWIN_INLINE HINSTANCE AFXAPI AfxGetInstanceHandle(){ ASSERT(afxCurrentInstanceHandle != NULL); return afxCurrentInstanceHandle; }_AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle(){ ASSERT(afxCurrentResourceHandle != NULL); return afxCurrentResourceHandle; }_AFXWIN_INLINE void AFXAPI AfxSetResourceHandle(HINSTANCE hInstResource){ ASSERT(hInstResource != NULL); afxCurrentResourceHandle = hInstResource;}实际上访问的就是afxCurrentInstanceHandle,afxCurrentResourceHandle。/////////////////////////////////////////////////////////////////////////////// Global functions for access to the one and only CWinApp#define afxCurrentInstanceHandle AfxGetModuleState()->m_hCurrentInstanceHandle#define afxCurrentResourceHandle AfxGetModuleState()->m_hCurrentResourceHandleAFX_MODULE_STATE* AFXAPI AfxGetModuleState(){ _AFX_THREAD_STATE* pState = _afxThreadState; AFX_MODULE_STATE* pResult; if (pState->m_pModuleState != NULL) { // thread state's module state serves as override pResult = pState->m_pModuleState; } else { // otherwise, use global app state pResult = _afxBaseModuleState.GetData(); } ASSERT(pResult != NULL); return pResult;}
其中的AFX_THREAD_STATE在此我们就不讨论了,有兴趣的读者可以阅读(afxstat.h和afxstate.cpp)。那AfxGetModuleState()->m_hCurrentResourceHandle又是在哪初始化的呢?
我们可以在appinit.cpp中的BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)看到
// set resource handles
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pModuleState->m_hCurrentInstanceHandle = hInstance;
pModuleState->m_hCurrentResourceHandle = hInstance;
和appinit.cpp中的void CWinApp::SetCurrentHandles()中看到
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
pModuleState->m_hCurrentInstanceHandle = m_hInstance;
pModuleState->m_hCurrentResourceHandle = m_hInstance;
CWinApp::SetCurrentHandles()也是由AfxWinInit调用的,那AfxWinInit又由谁调用呢?
我们可以在DllMain(dllinit.cpp和dllmodul.cpp,分别对应于MFC扩展DLL和MFC规则DLL)看到
(dllinit.cpp,MFC扩展DLL)static AFX_EXTENSION_MODULE coreDLL;….extern "C"BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID){ if (dwReason == DLL_PROCESS_ATTACH) { ……. // initialize this DLL's extension module VERIFY(AfxInitExtensionModule(coreDLL, hInstance)); #ifdef _AFX_OLE_IMPL AfxWinInit(hInstance, NULL, _T(""), 0); …. #endif …. // wire up this DLL into the resource chain CDynLinkLibrary* pDLL = new CDynLinkLibrary(coreDLL, TRUE); ASSERT(pDLL != NULL); pDLL->m_factoryList.m_pHead = NULL; …. } else if (dwReason == DLL_PROCESS_DETACH) { …. // cleanup module state for this process AfxTermExtensionModule(coreDLL); …. // cleanup module state in OLE private module state AfxTermExtensionModule(coreDLL, TRUE); …. } …}
可以看到在提供自动化支持时,将调用AfxWinInit(但MFC的DLL向导,对于扩展DLL却不允许添加自动化支持)。
#ifdef _AFXDLLstatic AFX_EXTENSION_MODULE controlDLL;….#endifextern "C"BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/){ if (dwReason == DLL_PROCESS_ATTACH) { …. _AFX_THREAD_STATE* pState = AfxGetThreadState(); AFX_MODULE_STATE* pPrevModState = pState->m_pPrevModuleState; // Initialize DLL's instance(/module) not the app's if (!AfxWinInit(hInstance, NULL, _T(""), 0)) { AfxWinTerm(); goto Cleanup; // Init Failed } …. #ifdef _AFXDLL // wire up this DLL into the resource chain VERIFY(AfxInitExtensionModule(controlDLL, hInstance)); CDynLinkLibrary* pDLL; pDLL = new CDynLinkLibrary(controlDLL); ASSERT(pDLL != NULL); #else AfxInitLocalData(hInstance); #endif … } else if (dwReason == DLL_PROCESS_DETACH) { …. #ifdef _AFXDLL AfxTermExtensionModule(controlDLL, TRUE); #else AfxTermLocalData(hInstance, TRUE); #endif } …}
- 动态链接库 (DLL)
- 动态链接库DLL
- 动态链接库DLL
- 动态链接库 dll
- DLL动态链接库
- DLL 动态链接库
- DLL(动态链接库)
- 动态链接库DLL
- DLL,动态链接库
- 动态链接库 DLL
- 动态链接库DLL
- 动态链接库 dll
- 动态链接库DLL
- 动态链接库DLL
- 动态链接库DLL
- 动态链接库DLL
- 动态链接库DLL
- 动态链接库DLL
- 解决SDK更新导致Eclispe中ADT版本太低不能启动
- InstaRecon – Automated Subdomain Discovery Tool
- 黑马程序员——第十章 设计模式
- hdu 1385 Minimum Transport Cost Floyd
- Django学习笔记--新建web工程步骤
- 动态链接库DLL
- 用C语言打印心形
- 登录博客园的第一天记录
- 编程基本功之数组求和
- MinGW使用介绍
- Android Studio 编码设置
- 常见iOS系统错误代码含义 英文版
- Django学习笔记--管理页面的创建与配置
- 屏幕旋转详解(自动旋转、手动旋转、兼容IOS6之前系统)