CLR 探查器:COM 样式的强制转换和从派生接口调用函数
CLR profiler: COM-style casting and calling functions from derived interfaces
我需要开发一个专门的CLR探查器。CLR 探查器必须实现为实现 ICorProfilerCallback
的 COM 服务器或当前到 5 的较新版本。探查器初始化发生在回调方法Initialize(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_pICorProfilerInfo
,其类型为 CComQIPtr<ICorProfilerInfo>
。然后,我调用它的方法,而不考虑实现该方法的对象的实际类型。
这让我想到两个问题:
- 在 COM/ATL 上下文中,检索派生接口,将它们存储在父接口中(如上所示),然后从中调用函数是否安全?
- 父接口显然不了解派生接口中的函数。如何检查指针是否是派生接口(例如
ICorProfilerInfo2
)并将其转换为派生接口?
在到目前为止的测试中,#1 通常看起来还可以。但我更喜欢确认或建议。我对#2点更加不确定。例如,ICorProfilerInfo
具有SetEnterLeaveFunctionHooks
函数,而ICorProfilerInfo2
具有SetEnterLeaveFunctionHooks2
函数。我想做一些类似于以下伪代码的事情:
if (m_pICorProfilerInfo IS ICorProfilerInfo2)
{
((ICorProfilerInfo2) m_pICorProfilerInfo)->SetEnterLeaveFunctionHooks2(...)
}
else
{
m_pICorProfilerInfo->SetEnterLeaveFunctionHooks(...)
}
关于如何做到这一点的任何建议将不胜感激。
1) 对于这些接口类型是可以的,它们被精心设计为始终继承以前的版本。 因此,ICorProfilerInfo4 的向量表包括了 3 个先前版本的所有方法。 对于COM接口来说,这当然不一定总是如此,但在这里有效。 这是危险的,当您获得ICorProfilerInfo3接口时调用ICorProfilerInfo4方法会使程序崩溃。 你不会从编译器那里得到任何帮助来让你远离麻烦。
2)C++中没有IS运算符,您可以通过再次调用QueryInterface()在COM中执行此操作。 或者,您可以设置一个变量来指示您获得的接口版本。 使用 QI 可以避免在版本检查错误时崩溃,并允许编译器帮助您正确获取代码。
我建议您首先对实际需要的分析器功能进行编目。 你面临着增加太多灵活性的危险,这种灵活性会让你编写你永远不会使用的代码,并发布一个未经充分测试的程序。 FunctionEnter2 和 FunctionEnter3 之间的差异并不微妙,但是两者都可以正常工作,您不太可能注意到优化。
- 存储模板类型以强制转换回派生<T>
- 在 C++ 中将对象转换为派生类型
- 从基类实例调用派生类方法而不进行强制转换
- 从基指针到派生的强制转换问题
- C++将派生类转换为基类时'object slicing'期间发生的情况
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- C ++基础私有方法在将自身转换为派生类后可以访问吗?
- 调用不在基类中的派生类函数而不进行动态强制转换,以最大程度地提高性能
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 我们可以在不知道其真实类型的情况下将基类指针转换为派生类指针吗?
- 为什么从基转换为派生提供此功能?
- 将基本实例指针强制转换为派生实例指针是否合法?(实例不是派生实例)
- 从从该抽象类派生的 Python 对象强制转换C++抽象类C++
- 基类到派生类的强制转换向量
- 有没有办法复制派生类指针的向量而不将其强制转换为基类?
- 为什么此代码不将基类强制转换为 c++ 中的派生类?
- 如何在运行时将指向派生类的 void* 正确转换为指向基类的 void*
- C++转换派生类
- CRTP / 宏 / 避免强制转换派生类的指针
- 如何正确转换派生类