C++ CLR探查器:COM风格的从派生接口转换和调用函数

C++ CLR探查器:COM风格的从派生接口转换和调用函数,c++,com,atl,clr-profiling-api,C++,Com,Atl,Clr Profiling Api,我需要开发一个专门的CLR分析器。CLR探查器必须作为COM服务器实现ICorProfilerCallback或当前升级到5的更新版本。探查器初始化在回调方法初始化(IUnknown*pICorProfilerInfoUnk)中进行。这使您有机会对提供的IUnknown对象执行QueryInterface,并获取指向ICorProfilerInfo接口的指针。从.NET 4.5开始,共有ICorProfilerInfo、ICorProfilerInfo2、ICorProfilerInfo3和IC

我需要开发一个专门的CLR分析器。CLR探查器必须作为COM服务器实现
ICorProfilerCallback
或当前升级到5的更新版本。探查器初始化在回调方法
初始化(IUnknown*pICorProfilerInfoUnk)
中进行。这使您有机会对提供的
IUnknown
对象执行
QueryInterface
,并获取指向
ICorProfilerInfo
接口的指针。从.NET 4.5开始,共有
ICorProfilerInfo
ICorProfilerInfo2
ICorProfilerInfo3
ICorProfilerInfo4
,每个新版本都提供了额外的功能。理想情况下,我希望获得一个指向最新可用版本的指针,并让vtables找出真正的对象是什么

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_picorprofileinfo
,其类型为
CComQIPtr
。然后我调用它的方法,而不知道实现该方法的对象的实际类型

这就引出了两个问题:

  • 在COM/ATL上下文中,检索派生接口、将它们存储在如上所述的父接口中,然后从中调用函数是否安全
  • 父接口显然不知道派生接口中的函数。如何检查指针是否为派生接口(如
    icorprofileinfo2
    ),并将其强制转换为派生接口
  • 到目前为止,在测试中,#1通常看起来还可以。但我更喜欢确认或建议。我对第二点更不确定。例如,
    ICorProfilerInfo
    有一个
    SetEnterLeaveFunctionHooks
    函数,而
    ICorProfilerInfo2
    有一个
    SetEnterLeaveFunctionHooks2
    函数。我想做一些类似于以下伪代码的事情:

    if (m_pICorProfilerInfo IS ICorProfilerInfo2)
    {
        ((ICorProfilerInfo2) m_pICorProfilerInfo)->SetEnterLeaveFunctionHooks2(...)
    }
    else
    {
        m_pICorProfilerInfo->SetEnterLeaveFunctionHooks(...)
    }
    
    任何关于如何实现这一点的建议都将不胜感激。

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

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


    我建议您首先对实际需要的分析器功能进行分类。您可能会增加太多的灵活性,这种灵活性会让您编写永远不会使用的代码,并发布一个未经充分测试的程序。FunctionEnter2和FunctionEnter3之间的区别并不微妙,但两者都可以正常工作,您不太可能注意到优化。

    感谢您的回复。我决定使用CComQIPtr并检查NULL来实现IS/AS。关于灵活性的观点。虽然这可能仍然是一种内部工具,用于协助开发和QA,因此风险较小(尽管仍然很重要)。