visual-c++ - 在 MFC+ATL EXE 中使用带有未注册接口(interface)的 IDispatchImpl

标签 visual-c++ com mfc atl visual-c++-2010

我开始这个项目是作为一个 MFC 应用程序(用于 GUI..),后来添加了对 ATL 的支持。

然后我编写了一个简单的 ATL-COM 对象,使用 IDispatchImpl 实现了一个非注册双接口(interface),0xfff 代表 Major 和 Minor,告诉 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 在注册表中。要实现未注册的接口(interface),您可以使用 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 并且 ATL 将尝试从模块加载类型库,而不是从注册表加载类型库,前提是您的 CAtlModule: :m_libid 是最新的。 CAtlModule::m_libid 预计如何保持最新状态?通过使用 DECLARE_LIBID 宏。该宏如何工作?通过定义静态 InitLibId 函数,它设置 CAtlModule::m_libid

错误:当您的模块派生自 ATL::CAtlMfcModule 时,不会调用定义的 InitLibId 函数(因为 ATL::CAtlMfcModule 不是类模板)

最佳答案

你是对的,如果你对主要/次要版本使用 -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>

如果您在 MS Connect 上发布它作为一个错误,你可以在这里留下一个链接,让其他人去投票赞成这个错误。

关于visual-c++ - 在 MFC+ATL EXE 中使用带有未注册接口(interface)的 IDispatchImpl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20152185/

相关文章:

c++ - 将 VC++ 解决方案和项目文件从 32 位转换为 64 位

c++ - 使用 SetTimer 传递用户数据

c# - 处理从 C++/MFC 应用程序中的 .NET dll 抛出的异常

mfc - 定位与资源对话框中的另一个控件重叠的动态创建的控件会导致奇怪的行为

c++ - PutFile 不从事件目录发送文件?

c++ - LPtoDP 功能如何运作?

c++ - 错误 C2039 : 'type_name' : is not a member of of 'swig::traits<Bar>'

c++ - 如何将 wcstombs 转换为 wcstombs_s

windows - 使用 Inno Setup 安装程序安装 Windows shell 扩展 DLL

c++ - 从进程外 COM 服务器返回接口(interface)指针的正确方法是什么?