我需要开发一个专门的CLR分析器。 CLR分析器必须实现为实现ICorProfilerCallback
的COM服务器或当前最高版本为5的较新版本。分析器初始化发生在回调方法Initialize(IUnknown* pICorProfilerInfoUnk)
中。这使得有机会在提供的QueryInterface
对象上执行IUnknown
并获取指向ICorProfilerInfo
接口的指针。从.NET 4.5开始,有ICorProfilerInfo
,ICorProfilerInfo2
,ICorProfilerInfo3
和ICorProfilerInfo4
,每个新版本都提供其他功能。理想情况下,我想获得一个指向最新可用版本的指针,让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>
。然后我调用它上面的方法,忽略了实现该方法的对象的实际类型。
这引出了两个问题:
ICorProfilerInfo2
)并将其转换为此类?到目前为止的测试中,#1通常看起来没问题。但我宁愿确认或建议。关于第2点,我更加不确定。例如,ICorProfilerInfo
具有SetEnterLeaveFunctionHooks
函数,而ICorProfilerInfo2
具有SetEnterLeaveFunctionHooks2
函数。我想做类似下面的伪代码:
if (m_pICorProfilerInfo IS ICorProfilerInfo2)
{
((ICorProfilerInfo2) m_pICorProfilerInfo)->SetEnterLeaveFunctionHooks2(...)
}
else
{
m_pICorProfilerInfo->SetEnterLeaveFunctionHooks(...)
}
关于如何实现这一目标的任何建议都将非常受欢迎。
答案 0 :(得分:2)
1)对于这些接口类型是可以的,它们被精心设计为始终继承以前的版本。因此,ICorProfilerInfo4的v表包含以前3个版本的方法的所有。对于COM接口来说,当然不一定总是这样,但在这里工作。这很危险,当您获得ICorProfilerInfo3接口时调用ICorProfilerInfo4方法会使程序崩溃。你没有得到编译器的帮助,以免你遇到麻烦。
2)C ++中没有IS运算符,可以通过再次调用QueryInterface()在COM中完成。或者您可以设置一个变量来指示您获得的接口版本。使用QI可以避免在版本检查错误时发生崩溃,并且 允许编译器帮助您正确获取代码。
我建议您首先编制实际需要的分析器功能。你有增加太多灵活性的危险,那种让你编写你永远不会使用的代码并运送未经过全面测试的程序。 FunctionEnter2和FunctionEnter3之间的差异不是很微妙,但两者都可以正常工作,你很可能不会注意到优化。