我以MFC应用程序(用于GUI.)的形式启动了该项目,并随后添加了对ATL的支持。
然后,我使用IDispatchImpl编写了一个简单的ATL对象,实现了一个未注册的双接口,其中包含了0 0xfff,用于主和次要接口,以告诉ATL从EXE加载TLB。
我跳过了一些细节,但是在调试之后,我发现atlcom.h中的CComTypeInfoHolder::GetTI实现并没有试图从EXE加载TLB,而是在注册表中搜索它。原因: m_plibid变量与我的ATL::CAtlMfcModule声明中的DECLARE_LIBID宏使用不相对应。
在module之后,我找到了Bug: CAtlMfcModule::InitLibId()未调用,并在我的模块CTOR中添加了一个对InitLibId的调用。
现在工作得很好。
问:那是已知的窃听器吗?用已知的方法?我不适合解决这样一个老问题。有别的办法处理吗?
更新:附加信息,如答案所述,没有错误.
IDispatchImpl类
在默认情况下,IDispatchImpl类在注册表中查找T的类型信息。要实现未注册的接口,可以使用IDispatchImpl类,而无需使用预定义的版本号访问注册表。如果创建一个IDispatchImpl对象,其中0xFFFF作为wMajor的值,0xFFFF作为wMinor的值,则IDispatchImpl类将从.dll文件检索类型库,而不是从注册表.检索类型库。
摘录自CComTypeInfoHolder::GetTI在atlcom.h中的实现
if (InlineIsEqualGUID( CAtlModule::m_libid, *m_plibid) &&
m_wMajor == 0xFFFF &&
m_wMinor == 0xFFFF ) {
TCHAR szFilePath[MAX_PATH];
DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH);
[...]
hRes = LoadTypeLib(pszFile, &pTypeLib);
} else {
[...]
hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib);因此,在我看来,显然存在一种广告行为:将0 0xffff用于次要和专业,如果您的CAtlModule::m_libid是最新的,那么ATL将尝试从模块而不是从注册表加载类型。CAtlModule::m_libid是如何被期望是最新的?通过使用DECLARE_LIBID宏。这个宏是如何工作的?通过定义静态InitLibId函数来设置CAtlModule::m_libid。
bug:当您的模块从ATL::CAtlMfcModule派生时,定义的InitLibId函数不会被调用(因为ATL::CAtlMfcModule不是类模板)
发布于 2013-11-24 00:31:22
您是正确的,如果您在主要/次要版本中使用-1,则假定类型信息将从二进制文件中获取。然而,这并不适用于MFC项目:DECLARE_LIBID只适用于CAtlMfcModule类,而不是其后代。
快速修复可能是这样的,在atlbase.h:
//class CAtlMfcModule :
// public ATL::CAtlModuleT<CAtlMfcModule>
template <typename T>
class CAtlMfcModuleT :
public ATL::CAtlModuleT<T>然后在你的项目中:
//class CMFCApplication1Module :
// public ATL::CAtlMfcModule
class CMFCApplication1Module :
public ATL::CAtlMfcModuleT<CMFCApplication1Module>如果您将它作为bug发布在康奈特上,您可以在这里留下一个链接,供其他人使用。
https://stackoverflow.com/questions/20152185
复制相似问题