【问题标题】:ATL COM code will not compile on upgrade to VS2015ATL COM 代码在升级到 VS2015 时不会编译
【发布时间】:2016-11-18 07:14:15
【问题描述】:

乡亲

我正在将旧版应用程序从 VS2008 升级到 VS2015。它非常依赖 ATL 和 COM。我注意到 atlbase.h 中 _ATL_COM_MODULE70 的变化导致了问题。

在 ...\9.0\VC\atlmfc\include\atlbase.h 中定义为:

struct _ATL_COM_MODULE70
{
  UINT cbSize;
  HINSTANCE m_hInstTypeLib;
  _ATL_OBJMAP_ENTRY** m_ppAutoObjMapFirst;
  _ATL_OBJMAP_ENTRY** m_ppAutoObjMapLast;
  CComCriticalSection m_csObjMap;
};

但是在 ...\14.0\VC\atlmfc\include\atlcom.h 中它被定义为:

struct _ATL_COM_MODULE70
{
    UINT cbSize;
    HINSTANCE m_hInstTypeLib;
    _ATL_OBJMAP_ENTRY_EX** m_ppAutoObjMapFirst;
    _ATL_OBJMAP_ENTRY_EX** m_ppAutoObjMapLast;
    CComCriticalSection m_csObjMap;
};

这会导致以下代码无法编译:

HRESULT FreeThreadSingletons (void)
{
    for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++)
    {
        if (*ppEntry != NULL)
        {
            _ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
            CComClassFactoryThreadSingleton *pThread;
            if ((pThread = dynamic_cast<CComClassFactoryThreadSingleton *>(pEntry->pCF)) != NULL)
            {
                pThread->ReleaseAllObjects ();
            }
        }
    }

    return S_OK;
}

原因是因为 m_ppAutoObjMapFirst 在 VC14 中是 _ATL_OBJMAP_ENTRY_EX 类型,在 VC9 中是 _ATL_OBJMAP_ENTRY 类型。

Microsoft 的 VS2015 文档说 VC14 中的结构应该与 VC9 中的相同: https://msdn.microsoft.com/en-us/library/ayw1b6h5.aspx

现在回答问题。过去有没有人见过这个问题,是否有不涉及将所有内容重写到 _ATL_OBJMAP_ENTRY_EX 接口的解决方法?

【问题讨论】:

  • "documentation... 说结构应该是相同的"实际上并非如此,因此您只需要分别更新FreeThreadSingletons,以反映_ATL_OBJMAP_ENTRY_ATL_OBJMAP_ENTRY_EX 的变化。

标签: c++ com atl


【解决方案1】:

感谢 H. Guijit 的回复。以下是微软的回应:

正如您已经注意到的,MSDN 中 _ATL_COM_MODULE70 结构的文档是不准确的。

_ATL_OBJMAP_ENTRY 和 _ATL_OBJMAP_ENTRY_EX 是 atlbase.h 中定义的两个不同结构的 typedef

不幸的是,您已经成为依赖于可能更改的内部结构和实现的代码的受害者。

这不是我读过的最有用的东西..

我已更改代码以从 pCache->pCF 检索 IUnknown

HRESULT FreeThreadSingletons (void)
{
    for (_ATL_OBJMAP_ENTRY_EX** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++)
    {
        if (*ppEntry != NULL)
        {
            _ATL_OBJMAP_ENTRY_EX* pEntry = *ppEntry;
            CComClassFactoryThreadSingleton *pThread;
            if ((pThread = dynamic_cast<CComClassFactoryThreadSingleton *>((pEntry->pCache)->pCF)) != NULL)
            {
                pThread->ReleaseAllObjects ();
            }
        }
    }

    return S_OK;
}

我不确定这是否可行,因为我仍在与构建问题作斗争,但希望在一两天内运行该应用程序。

【讨论】:

    【解决方案2】:

    你可以这样改写:

    for(auto ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++)
    

    无论指针的类型如何,这始终是正确的。

    我想你可以避免使用一些预处理器魔法来修改你的源代码,但我认为这样做对可维护性来说有点灾难。

    至于过去看到过这种情况......微软经常扩展现有的结构和函数,当他们这样做时,扩展的结构或函数会在其名称后附加“ex”。 'ex' 结构通常(总是?)与旧版本相同,只是有额外的字段。与“ex”函数相同,通常只是获取一些额外的参数。

    【讨论】:

    • 唉,在这种情况下,_ATL_OBJMAP_ENTRY 和 _ATL_OBJMAP_ENTRY_EX 是明显不同的内容。这不是 for 循环中的指针类型,我担心它必须更改所有用于使用 _ATL_OBJMAP_ENTRY 的代码。但如果必须完成,就必须完成......
    • 唯一的区别似乎是替换pCF和dwRegister的pCache成员,但我当然不知道这对你有多糟糕......
    猜你喜欢
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    • 2013-04-15
    相关资源
    最近更新 更多