在升级到VS2015时,ATL COM代码无法编译

时间:2016-07-15 07:12:08

标签: c++ com atl

民间

我正在将遗留应用程序从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接口的所有内容?

2 个答案:

答案 0 :(得分:1)

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

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

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

不幸的是,您已经成为依赖于可能发生变化的内部结构和实现的代码的牺牲品。

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

我已更改代码以从pCache-&gt; 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;
}

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

答案 1 :(得分:0)

您可以这样重写:

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

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

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

至于在过去看过这个...微软经常扩展现有的结构和功能,当他们做扩展的结构或功能时,得到了&#39; ex&#39;附在其名称上。 &#39; EX&#39;结构通常(总是?)与旧版本相同,只是有额外的字段。与&#39; ex&#39;相同函数,通常只是获得一些额外的参数。