我以MFC应用程序(用于GUI ..)开始了该项目,后来又增加了对ATL的支持。
然后,我使用IDispatchImpl编写了一个简单的ATL-COM对象,该对象使用IDispatchImpl来实现未注册的双接口,主要和次要对象使用0xfff,以告诉ATL从EXE加载TLB。
我跳过了一些细节,但是最后,在进行一些调试之后,我发现atlcom.h中的CComTypeInfoHolder :: GetTI实现不是试图从EXE加载TLB,而是在注册表中搜索它。原因:m_plibid变量与我的ATL :: CAtlMfcModule声明中使用的DECLARE_LIBID宏不对应。
经过一番谷歌搜索后,我发现Bug: CAtlMfcModule::InitLibId() not called并在模块CTOR中添加了对InitLibId的调用。
现在很好。
问题:那是一个已知的错误吗?有一个已知的解决方案?我对这样一个旧错误的解决方法不满意。还有另一种处理方法吗?
更新:其他信息,作为回答指出没有错误...
通过默认,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);
所以,对我来说似乎很明显,有一个[[广告行为]]:对次要和主要使用0xffff,并且只要您的CAtlModule :: m_libid已启动,ATL就会尝试从模块而不是从注册表加载typelib。至今。 CAtlModule :: m_libid如何保持最新状态?通过使用DECLARE_LIBID
宏。该宏如何工作?通过定义一个静态的InitLibId
函数来设置CAtlModule::m_libid
。错误:当您的模块从ATL::CAtlMfcModule
派生时,未调用已定义的InitLibId函数(因为ATL :: CAtlMfcModule不是类模板)
我以MFC应用程序(用于GUI ..)开始了该项目,后来又增加了对ATL的支持。然后,我使用IDispatchImpl编写了一个实现未注册双接口的简单ATL-COM对象,...
-1
用于主要/次要版本,则假定类型信息将从二进制文件中获取。但是,这不适用于MFC项目:DECLARE_LIBID
仅适用于CAtlMfcModule
类,但不适用于其后代。