CLR分析器:派生接口的COM样式转换和调用函数

时间:2013-11-09 06:55:41

标签: c++ com atl clr-profiling-api

我需要开发一个专门的CLR分析器。 CLR分析器必须实现为实现ICorProfilerCallback的COM服务器或当前最高版本为5的较新版本。分析器初始化发生在回调方法Initialize(IUnknown* pICorProfilerInfoUnk)中。这使得有机会在提供的QueryInterface对象上执行IUnknown并获取指向ICorProfilerInfo接口的指针。从.NET 4.5开始,有ICorProfilerInfoICorProfilerInfo2ICorProfilerInfo3ICorProfilerInfo4,每个新版本都提供其他功能。理想情况下,我想获得一个指向最新可用版本的指针,让vtable找出真实对象是什么。

if (FAILED(pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo4, (LPVOID*)&m_pICorProfilerInfo)))
{
    if (FAILED(pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo3, (LPVOID*)&m_pICorProfilerInfo)))
    {
        if (FAILED(pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo2, (LPVOID*)&m_pICorProfilerInfo)))
        {
            if (FAILED(pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo, (LPVOID*)&m_pICorProfilerInfo)))
            {
                AtlTrace(TEXT("[Initialize] Failed to retrieve any ICorProfilerInfo~ interface."));
                return S_FALSE;
            }
        }
    }
}

请注意,所有情况下,返回接口的指针都是同一个变量m_pICorProfilerInfo,类型为CComQIPtr<ICorProfilerInfo>。然后我调用它上面的方法,忽略了实现该方法的对象的实际类型。

这引出了两个问题:

  1. 在COM / ATL上下文中,检索派生接口,将它们存储在上面的父接口中,然后从中调用函数是否安全?
  2. 父接口显然不了解派生接口中的函数。如何检查指针是否为派生接口(例如ICorProfilerInfo2)并将其转换为此类?
  3. 到目前为止的测试中,#1通常看起来没问题。但我宁愿确认或建议。关于第2点,我更加不确定。例如,ICorProfilerInfo具有SetEnterLeaveFunctionHooks函数,而ICorProfilerInfo2具有SetEnterLeaveFunctionHooks2函数。我想做类似下面的伪代码:

    if (m_pICorProfilerInfo IS ICorProfilerInfo2)
    {
        ((ICorProfilerInfo2) m_pICorProfilerInfo)->SetEnterLeaveFunctionHooks2(...)
    }
    else
    {
        m_pICorProfilerInfo->SetEnterLeaveFunctionHooks(...)
    }
    

    关于如何实现这一目标的任何建议都将非常受欢迎。

1 个答案:

答案 0 :(得分:2)

1)对于这些接口类型是可以的,它们被精心设计为始终继承以前的版本。因此,ICorProfilerInfo4的v表包含以前3个版本的方法的所有。对于COM接口来说,当然不一定总是这样,但在这里工作。这很危险,当您获得ICorProfilerInfo3接口时调用ICorProfilerInfo4方法会使程序崩溃。你没有得到编译器的帮助,以免你遇到麻烦。

2)C ++中没有IS运算符,可以通过再次调用QueryInterface()在COM中完成。或者您可以设置一个变量来指示您获得的接口版本。使用QI可以避免在版本检查错误时发生崩溃,并且 允许编译器帮助您正确获取代码。

我建议您首先编制实际需要的分析器功能。你有增加太多灵活性的危险,那种让你编写你永远不会使用的代码并运送未经过全面测试的程序。 FunctionEnter2和FunctionEnter3之间的差异不是很微妙,但两者都可以正常工作,你很可能不会注意到优化。