将IDispatchImpl与MFC + ATL EXE中的未注册接口一起使用

问题描述 投票:1回答:2

我以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 Class

通过默认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对象,...

visual-c++ com mfc atl visual-c++-2010
2个回答
2
投票
您是正确的,如果您将-1用于主要/次要版本,则假定类型信息将从二进制文件中获取。但是,这不适用于MFC项目:DECLARE_LIBID仅适用于CAtlMfcModule类,但不适用于其后代。
© www.soinside.com 2019 - 2024. All rights reserved.