本主题提供有关如何使用调试器数据模型C++接口扩展和自定义调试器功能的概述。
调试器数据模型主机
调试器数据模型设计为组件化系统,可以托管在各种不同上下文中。 通常,数据模型托管在调试器应用程序的上下文中。 为了成为数据模型的主机,需要实现许多接口来公开调试器的核心方面:其目标、内存空间、计算器、符号和类型系统等。虽然这些接口由任何希望托管数据模型的应用程序实现,但它们由核心数据模型以及与数据模型互作的任何扩展使用。
核心接口集包括:
接口名称 | 说明 |
---|---|
IDebugHost | 调试主机的核心接口。 |
IDebugHostStatus | 允许客户端查询主机状态的接口。 |
IDebugHostContext | 主机中上下文的抽象(例如:特定目标、特定进程、特定地址空间等...) |
IDebugHostErrorSink | 由调用方实现的接口,用于从主机和数据模型的某些部分接收错误 |
IDebugHostEvaluator / IDebugHostEvaluator2 | 调试主机的表达式计算器。 |
IDebugHostExtensibility | 用于扩展主机或部分功能的接口(如表达式计算器)。 |
类型系统和符号接口为:
InterfaceName | 说明 |
---|---|
IDebugHostSymbols | 提供对符号的访问和解析的核心接口 |
IDebugHostSymbol / IDebugHostSymbol2 | 表示任何类型的单个符号。 特定符号是此接口的派生。 |
IDebugHostModule | 表示在进程中加载的模块。 这是一种符号。 |
IDebugHostType / IDebugHostType2 | 表示本机/语言类型。 |
IDebugHostConstant | 表示符号信息中的常量(例如:C++ 中的非类型模板参数) |
IDebugHostField | 表示结构或类中的字段。 |
IDebugHostData | 表示模块中的数据(在结构或类中,它是 IDebugHostField) |
IDebugHostBaseClass | 表示基类。 |
IDebugHostPublic | 表示 PDB 的公共表内的符号。 这没有与之关联的类型信息。 它是名称和地址。 |
IDebugHostModuleSignature | 表示模块签名 - 一个定义,它将按名称和/或版本匹配一组模块 |
IDebugHostTypeSignature | 表示类型签名 -- 一个定义,它将按模块和/或名称匹配一组类型 |
核心主机接口:IDebugHost
IDebugHost 接口是任何数据模型主机的核心接口。 它的定义如下:
DECLARE_INTERFACE_(IDebugHost, IUnknown)
{
STDMETHOD(GetHostDefinedInterface)(_COM_Outptr_ IUnknown** hostUnk) PURE;
STDMETHOD(GetCurrentContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
STDMETHOD(GetDefaultMetadata)(_COM_Outptr_ IKeyStore** defaultMetadataStore) PURE;
}
如果给定主机存在此类接口,GetHostDefinedInterface 方法将返回主机的主专用接口。 对于 Windows 调试工具,此处返回的接口是 IDebugClient(强制转换为 IUnknown)。
GetCurrentContext 方法返回一个接口,该接口表示调试器主机的当前状态。 这的确切含义留给主机,但它通常包括会话、进程和地址空间等内容,这些空间在调试主机的用户界面中处于活动状态。 返回的上下文对象基本上对调用方不透明,但对调试主机的调用之间传递是一个重要对象。 例如,当调用方读取内存时,必须知道要从中读取内存的进程和地址空间。 该概念封装在此方法返回的上下文对象的概念中。
GetDefaultMetadata 方法返回一个默认的元数据存储,当未传递显式元数据时,该存储可用于某些作(例如:字符串转换)。 这样,调试主机就可以控制呈现某些数据的方式。 例如,默认元数据可能包括 PreferredRadix 键,允许主机指示是否应在十进制或十六进制中显示序号(如果未指定)。
请注意,必须手动解析默认元数据存储上的属性值,并且必须传递要为其查询默认元数据的对象。 应使用 GetKey 方法代替 GetKeyValue。
状态接口:IDebugHostStatus
IDebugHostStatus 接口允许数据模型的客户端或调试主机查询调试主机状态的某些方面。 接口的定义如下:
DECLARE_INTERFACE_(IDebugHostStatus, IUnknown)
{
STDMETHOD(PollUserInterrupt)(_Out_ bool* interruptRequested) PURE;
}
PollUserInterrupt 方法用于查询调试主机的用户是否请求中断当前作。 例如,数据模型中的属性访问器可以调用任意代码(例如:JavaScript 方法)。 该代码可能需要任意时间。 为了使调试主机保持响应,任何可能需要任意时间的此类代码都应通过调用此方法来检查中断请求。 如果 interruptRequested 值返回为 true,则调用方应立即中止并返回E_ABORT的结果。
上下文接口:IDebugHostContext
上下文是数据模型和基础调试主机最重要的方面之一。 保存对象时,必须能够知道对象来自何处 -- 它所处的进程、与之关联的地址空间。 了解此信息可正确解释指针值等内容。 类型 IDebugHostContext 的对象必须传递给调试主机上的许多方法。 可以通过多种方式获取此接口:
- 通过获取调试器的当前上下文:调用 IDebugHost 的 GetCurrentContext 方法
- 通过获取对象的上下文:调用 IModelObject 的 GetContext 方法
- 通过获取符号的上下文:调用 IDebugHostSymbol 的 GetContext 方法
此外,在 IDebugHostContext 接口的上下文中,有两个值具有特殊含义,这些接口是从数据模型返回或传递给数据模型或调试主机方法:
nullptr:指示没有上下文。 某些对象没有上下文是完全有效的。 数据模型的根命名空间中的 Debugger 对象不引用特定进程或地址空间中的任何内容。 它没有上下文。
USE_CURRENT_HOST_CONTEXT:一个 sentinel 值,指示应使用调试主机的当前 UI 上下文。 此值永远不会从调试主机返回。 但是,它可以传递给任何接受输入 IDebugHostContext 的调试主机方法,而不是显式调用 IDebugHost 的 GetCurrentContext 方法。 请注意,显式传递USE_CURRENT_HOST_CONTEXT通常比显式获取当前上下文的性能更高。
主机上下文的上下文与调用方基本上不透明。 核心调试主机外部调用方可以使用主机上下文执行的唯一作是将其与另一个主机上下文进行比较。
IDebugHostContext 接口的定义如下:
DECLARE_INTERFACE_(IDebugHostContext, IUnknown)
{
STDMETHOD(IsEqualTo)(_In_ IDebugHostContext *pContext, _Out_ bool *pIsEqual) PURE;
}
IsEqualTo 方法将主机上下文与其他主机上下文进行比较。 如果这两个上下文是等效的,则返回此指示。 请注意,此比较不是接口等效性。 这会比较上下文本身的基础不透明内容。
错误接收器:IDebugHostErrorSink
IDebugHostErrorSink 是客户端可以接收某些作期间发生的错误的通知,并在需要时路由这些错误。 接口的定义如下:
enum ErrorClass
{
ErrorClassWarning,
ErrorClassError
}
DECLARE_INTERFACE_(IDebugHostErrorSink, IUnknown)
{
STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrError, _In_ PCWSTR message) PURE;
}
ReportError 方法是错误接收器的回调,以通知错误已发生,并允许接收器将错误路由到任何 UI 或机制是否合适。
主机计算器:IDebugHostEvaluator/ IDebugHostEvaluator2
调试主机提供给客户端的最重要功能之一是访问其基于语言的表达式计算器。 IDebugHostEvaluator 和 IDebugHostEvaluator2 接口是从调试主机访问该功能的方法。
接口的定义如下:
DECLARE_INTERFACE_(IDebugHostEvaluator2, IDebugHostEvaluator)
{
//
// IDebugHostEvaluator:
//
STDMETHOD(EvaluateExpression)(_In_ IDebugHostContext* context, _In_ PCWSTR expression, _In_opt_ IModelObject* bindingContext, _COM_Errorptr_ IModelObject** result, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(EvaluateExtendedExpression)(_In_ IDebugHostContext* context, _In_ PCWSTR expression, _In_opt_ IModelObject* bindingContext, _COM_Errorptr_ IModelObject** result, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
//
// IDebugHostEvaluator2:
//
STDMETHOD(AssignTo)(_In_ IModelObject* assignmentReference, _In_ IModelObject* assignmentValue, _COM_Errorptr_ IModelObject** assignmentResult, _COM_Outptr_opt_result_maybenull_ IKeyStore** assignmentMetadata) PURE;
}
EvaluateExpression 方法允许请求调试主机计算语言(例如:C++)表达式,并返回作为 IModelObject 装箱的该表达式计算的结果值。 该方法的这种特定变体仅允许语言构造。 在语言(例如:LINQ 查询方法)中不存在的调试主机的表达式计算器中显示的任何其他功能都已关闭计算。
EvaluateExtendedExpression 方法类似于 EvaluateExpression 方法,只是它重新启用特定调试主机选择添加到其表达式计算器的其他非语言功能。 例如,对于 Windows 调试工具,这可实现匿名类型、LINQ 查询、模块限定符、格式说明符和其他非 C/C++ 功能。
IDebugHostEvaluator2
AssignTo 方法根据所调试的语言的语义执行赋值。
主机扩展性接口:IDebugHostExtensibility
调试主机的某些功能(可选)受扩展性的约束。 例如,这可能包括表达式计算器。 IDebugHostExtensibility 接口是访问这些扩展点的方法。 接口的定义如下:
DECLARE_INTERFACE_(IDebugHostExtensibility, IUnknown)
{
STDMETHOD(CreateFunctionAlias)(_In_ PCWSTR aliasName, _In_ IModelObject *functionObject) PURE;
STDMETHOD(DestroyFunctionAlias)(_In_ PCWSTR aliasName) PURE;
}
CreateFunctionAlias 方法为某些扩展中实现的方法创建“函数别名”、“快速别名”。 此别名的含义特定于主机。 它可以使用函数扩展主机的表达式计算器,也可以执行完全不同的操作。
DestroyFunctionAlias 方法撤消对 CreateFunctionAlias 方法的先前调用。 该函数将不再在快速别名下可用。
首先,数据模型扩展性 API 旨在与充当数据模型的主机的应用程序(通常是调试器)保持中立。 从理论上讲,任何应用程序都可以通过提供一组主机 API 来托管数据模型,这些 API 公开应用程序的调试目标的类型系统,并将一组投影对象公开到数据模型的命名空间中,了解目标、进程、线程等...位于这些调试目标(s) 中。
虽然数据模型 API(即开始 IDataModel、IDebugHost和 IModelObject 的分支)设计为可移植,但它们不定义什么是“调试器扩展”。 目前,希望扩展适用于 Windows 的调试工具及其提供的引擎的组件必须编写引擎扩展才能访问数据模型。 该引擎扩展只需要作为引擎扩展,就像扩展的加载和引导机制一样。 因此,最少的实现将提供:
- DebugExtensionInitialize:一种利用创建的 IDebugClient 访问数据模型并设置对象模型作的方法。
- DebugExtensionUninitialize:撤消在 DebugExtensionInitialize 中执行的对象模型作的方法。
- DebugExtensionCanUnload:返回扩展是否可以卸载的方法。 如果扩展中仍有实时 COM 对象,则必须指示这一点。 这是调试器的等效 COM DllCanUnloadNow。 如果返回无法卸载的S_FALSE指示,调试器稍后可以查询此状态,以查看卸载是否安全,或者它可能再次调用 DebugExtensionInitialize 重新初始化扩展。 扩展必须准备好处理这两个路径。
- DebugExtensionUnload:在 DLL 卸载之前执行任何最终清理的方法
Bridge 接口:IHostDataModelAccess
如前所述,调用 DebugExtensionInitialize 时,它将创建调试客户端并获取对数据模型的访问。 此类访问由 Windows 调试工具的旧 IDebug* 接口和数据模型之间的桥接口提供。 此桥接口为“IHostDataModelAccess”,定义如下:
DECLARE_INTERFACE_(IHostDataModelAccess, IUnknown)
{
STDMETHOD(GetDataModel)(_COM_Outptr_ IDataModelManager** manager, _COM_Outptr_ IDebugHost** host) PURE;
}
GetDataModel 方法是桥接口上的方法,它提供对数据模型的两侧的访问:调试主机(调试器下边缘)由返回的 IDebugHost 接口表示数据模型的主要组件 -- 数据模型管理器由返回的 IDataModelManager 接口表示
数据模型主机
调试器数据模型设计为组件化系统,可以托管在各种不同上下文中。 通常,数据模型托管在调试器应用程序的上下文中。 为了成为数据模型的主机,需要实现许多接口来公开调试器的核心方面:其目标、内存空间、计算器、符号和类型系统等。虽然这些接口由任何希望托管数据模型的应用程序实现,但它们由核心数据模型以及与数据模型互作的任何扩展使用。
类型系统和符号接口为:
接口名称 | 说明 |
---|---|
IDebugHostSymbols | 提供对符号的访问和解析的核心接口 |
IDebugHostSymbol / IDebugHostSymbol2 | 表示任何类型的单个符号。 特定符号是此接口的派生。 |
IDebugHostModule | 表示在进程中加载的模块。 这是一种符号。 |
IDebugHostType / IDebugHostType2 | 表示本机/语言类型。 |
IDebugHostConstant | 表示符号信息中的常量(例如:C++ 中的非类型模板参数) |
IDebugHostField | 表示结构或类中的字段。 |
IDebugHostData | 表示模块中的数据(在结构或类中,它是 IDebugHostField) |
IDebugHostBaseClass | 表示基类。 |
IDebugHostPublic | 表示 PDB 的公共表内的符号。 这没有与之关联的类型信息。 它是名称和地址。 |
IDebugHostModuleSignature | 表示模块签名 - 一个定义,它将按名称和/或版本匹配一组模块 |
IDebugHostTypeSignature | 表示类型签名 -- 一个定义,它将按模块和/或名称匹配一组类型 |
其他核心接口包括:
接口名称 | 说明 |
---|---|
IDebugHost | 调试主机的核心接口。 |
IDebugHostStatus | 允许客户端查询主机状态的接口。 |
IDebugHostContext | 主机中上下文的抽象(例如:特定目标、特定进程、特定地址空间等...) |
IDebugHostErrorSink | 由调用方实现的接口,用于从主机和数据模型的某些部分接收错误 |
IDebugHostEvaluator / IDebugHostEvaluator2 | 调试主机的表达式计算器。 |
IDebugHostExtensibility | 用于扩展主机或部分功能的接口(如表达式计算器)。 |
主符号接口:IDebugHostSymbols
IDebugHostSymbols 接口是访问调试目标中的符号的主要起点。 可以从 IDebugHost 实例查询此接口,并定义如下:
DECLARE_INTERFACE_(IDebugHostSymbols, IUnknown)
{
STDMETHOD(CreateModuleSignature)(_In_z_ PCWSTR pwszModuleName, _In_opt_z_ PCWSTR pwszMinVersion, _In_opt_z_ PCWSTR pwszMaxVersion, _Out_ IDebugHostModuleSignature** ppModuleSignature) PURE;
STDMETHOD(CreateTypeSignature)(_In_z_ PCWSTR signatureSpecification, _In_opt_ IDebugHostModule* module, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
STDMETHOD(CreateTypeSignatureForModuleRange)(_In_z_ PCWSTR signatureSpecification, _In_z_ PCWSTR moduleName, _In_opt_z_ PCWSTR minVersion, _In_opt_z_ PCWSTR maxVersion, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
STDMETHOD(EnumerateModules)(_In_ IDebugHostContext* context, _COM_Outptr_ IDebugHostSymbolEnumerator** moduleEnum) PURE;
STDMETHOD(FindModuleByName)(_In_ IDebugHostContext* context, _In_z_ PCWSTR moduleName, _COM_Outptr_ IDebugHostModule **module) PURE;
STDMETHOD(FindModuleByLocation)(_In_ IDebugHostContext* context, _In_ Location moduleLocation, _COM_Outptr_ IDebugHostModule **module) PURE;
STDMETHOD(GetMostDerivedObject)(_In_opt_ IDebugHostContext *pContext, _In_ Location location, _In_ IDebugHostType* objectType, _Out_ Location* derivedLocation, _Out_ IDebugHostType** derivedType) PURE;
}
CreateModuleSignature 方法创建一个签名,该签名可用于按名称和(可选)按版本匹配一组特定模块。 模块签名有三个组件:
- 名称:匹配模块必须具有与签名中名称完全不区分大小写匹配的名称
- 最低版本:如果指定,匹配的模块必须具有至少与此版本一样高的最低版本。 版本以“A.B.C.D”格式指定,每个后续部分的重要性都低于前一部分。 只有第一段是必需的。
- 最大版本:如果指定,匹配的模块必须具有不高于此版本的最大版本。 版本以“A.B.C.D”格式指定,每个后续部分的重要性都低于前一部分。 只有第一段是必需的。
CreateTypeSignature 方法创建一个签名,该签名可用于通过包含模块和类型名称来匹配一组具体类型。 类型名称签名字符串的格式特定于正在调试的语言(和调试主机)。 对于 C/C++,签名字符串等效于 NatVis 类型规范。 也就是说,签名字符串是模板参数允许通配符(指定为 *)的类型名称。
CreateTypeSignatureForModuleRange
CreateTypeSignatureForModuleRange 方法创建一个签名,该签名可用于按模块签名和类型名称匹配一组具体类型。 这类似于 CreateTypeSignature 方法,只是除了传递特定模块来匹配签名外,调用方传递创建模块签名所需的参数(就像使用 CreateModuleSignature 方法创建模块签名一样)。
EnumerateModules 方法创建一个枚举器,用于枚举特定主机上下文中可用的每个模块。 该主机上下文可能封装进程上下文,或者它可能封装类似于 Windows 内核的内容。
FindModuleByName 方法将浏览给定的主机上下文,并找到具有指定名称的模块,并向其返回接口。 使用或不使用文件扩展名按名称搜索模块是合法的。
FindModuleByLocation 方法将浏览给定的主机上下文,并确定哪个模块包含指定位置提供的地址。 然后,它将返回此类模块的接口。
GetMostDerivedObject 将使用调试器的类型系统从其静态类型确定对象的运行时类型。 此方法仅使用类型系统层中提供的符号信息和启发式信息来执行此分析。 这些信息可能包括C++ RTTI(运行时类型信息)或对象虚拟函数表形状的分析。 它不包括 IModelObject 上的首选运行时类型概念等内容。 如果分析找不到运行时类型,或者找不到与传入方法的静态类型不同的运行时类型,则输入位置和类型可能会传出。由于这些原因,该方法不会失败。
核心单个符号接口:IDebugHostSymbol
可以从数据模型主机返回的每个符号都将以某种方式派生自 IDebugHostSymbol。 这是每个符号实现的核心接口,无论符号类型如何。 根据符号类型,给定的符号可以实现一组其他接口,这些接口返回的属性对由此接口表示的特定符号类型更为独特。 IDebugHostSymbol2 / IDebugHostSymbol 接口的定义如下:
DECLARE_INTERFACE_(IDebugHostSymbol2, IDebugHostSymbol)
{
//
// IDebugHostSymbol:
//
STDMETHOD(GetContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
STDMETHOD(EnumerateChildren)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
STDMETHOD(GetSymbolKind)(_Out_ SymbolKind *kind) PURE;
STDMETHOD(GetName)(_Out_ BSTR* symbolName) PURE;
STDMETHOD(GetType)(_Out_ IDebugHostType** type) PURE;
STDMETHOD(GetContainingModule)(_Out_ IDebugHostModule **containingModule) PURE;
STDMETHOD(CompareAgainst)(_In_ IDebugHostSymbol *pComparisonSymbol, _In_ ULONG comparisonFlags, _Out_ bool *pMatches) PURE;
//
// IDebugHostSymbol2
//
STDMETHOD(EnumerateChildrenEx)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _In_opt_ SymbolSearchInfo* searchInfo, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
}
请务必注意,此接口表示多种符号 -- 由 SymbolKind 枚举描述,其值如下所示:
Enumarant | 含义 |
---|---|
象征 | 未指定的符号类型 |
SymbolModule | 符号是一个模块,可以查询 IDebugHostModule |
SymbolType | 符号是一种类型,可以查询 IDebugHostType |
SymbolField | 符号是一个字段(结构或类中的数据成员),可以查询 IDebugHostField |
SymbolConstant | 符号是常量值,可以查询 IDebugHostConstant |
SymbolData | 符号是不是结构或类的成员且可查询 IDebugHostData 的数据 |
SymbolBaseClass | 符号是基类,可查询 IDebugHostBaseClass |
SymbolPublic | 该符号是模块的公共表中的一个条目(没有类型信息),并且可查询 IDebugHostPublic |
SymbolFunction | 符号是一个函数,可查询 IDebugHostData |
GetContext 方法返回符号有效上下文。 虽然这将表示符号所在的调试目标和进程/地址空间等内容,但它可能不像从其他方式检索的上下文那样具体(例如:从 IModelObject)。
EnumerateChildren 方法返回一个枚举器,该枚举器将枚举给定符号的所有子项。 例如,对于C++类型,基类、字段、成员函数等都被视为类型符号的子级。
模块接口:IDebugHostModule
调试器对在某些地址空间中加载的模块的概念以数据模型中的两种不同的方式表示:在类型系统级别通过 IDebugHostModule 接口。 在这里,模块是一个符号,模块的核心属性是通过 Debugger.Models.Module 数据模型在数据模型级别投影的接口方法调用。 这是模块的类型系统 IDebugHostModule 表示形式的可扩展封装。
IDebugHostModule 接口的定义如下(忽略 IDebugHostSymbol 的泛型方法):
DECLARE_INTERFACE_(IDebugHostModule, IDebugHostSymbol)
{
//
// IDebugHostModule:
//
STDMETHOD(GetImageName)(_In_ bool allowPath, _Out_ BSTR* imageName) PURE;
STDMETHOD(GetBaseLocation)(_Out_ Location* moduleBaseLocation) PURE;
STDMETHOD(GetVersion)(_Out_opt_ ULONG64* fileVersion, _Out_opt_ ULONG64* productVersion) PURE;
STDMETHOD(FindTypeByName)(_In_z_ PCWSTR typeName, _Out_ IDebugHostType** type) PURE;
STDMETHOD(FindSymbolByRVA)(_In_ ULONG64 rva, _Out_ IDebugHostSymbol** symbol) PURE;
STDMETHOD(FindSymbolByName)(_In_z_ PCWSTR symbolName, _Out_ IDebugHostSymbol** symbol) PURE;
}
GetImageName 方法返回模块的图像名称。 根据 allowPath 参数的值,返回的图像名称可能包含或不包含图像的完整路径。
GetBaseLocation 方法将模块的基本负载地址作为位置结构返回。 模块返回的位置结构通常引用虚拟地址。
GetVersion 方法返回有关模块的版本信息(假设此类信息可以成功读出标头)。 如果请求给定版本(通过非 nullptr 输出指针),并且无法读取,将从方法调用返回相应的错误代码。
FindTypeByName 方法通过类型名称查找模块中定义的类型,并为其返回类型符号。 此方法可能会返回一个有效的 IDebugHostType,该类型永远不会通过模块的子级的显式递归返回。 调试主机可能允许创建派生类型 -- 模块本身中从未使用过的类型,但派生自这些类型。 例如,如果在模块的符号中定义了 MyStruct 结构,但从未使用过 MyStruct 类型,FindTypeByName 方法可能会合法地返回 MyStruct 的类型符号 **,尽管该类型名称从未在模块的符号中显式显示。
FindSymbolByRVA 方法将在模块中的给定相对虚拟地址处查找单个匹配符号。 如果提供的 RVA 中没有单个符号(例如:存在多个匹配项),此方法将返回错误。 请注意,此方法首选返回专用符号而不是公共表中的符号。
FindSymbolByName 方法将在模块中找到给定名称的单个全局符号。 如果没有与给定名称匹配的单个符号,此方法将返回错误。 请注意,此方法首选返回专用符号而不是公共表中的符号。
访问类型系统:IDebugHostType2/ IDebugHostType
IDebugHostType2 或 IDebugHostType 接口描述了给定的语言/本机类型。 请注意,这些接口上的某些方法仅适用于特定类型的类型。 给定的类型符号可以引用 TypeKind 枚举描述的以下类型之一:
类型类型 | 说明 |
---|---|
TypeUDT | 用户定义的类型(结构、类、联合等)。一个模型对象,其类型为 TypeUDT 的本机类型具有 ObjectTargetObject 的规范表示形式,该类型始终保留在相应的 IModelObject 中。 |
TypePointer | 指针。 一个模型对象,其类型为 TypePointer 的本机类型具有 ObjectIntrinsic 的规范表示形式,其中指针的值将零扩展到VT_UI8,并保留为此 64 位形式的内部数据。 TypePointer 的任何类型符号都有一个基类型(由 GetBaseType 方法返回),该类型是指针指向的类型。 |
TypeMemberPointer | 指向类成员的指针。 一个模型对象,其类型为 TypeMemberPointer 的本机类型具有规范表示形式,它是固有的(值与指针值相同)。 此值的确切含义是特定于编译器/调试主机。 |
TypeArray | 数组。 一个模型对象,其类型为 TypeArray 的本机类型具有 ObjectTargetObject 的规范表示形式。 数组的基址是对象的位置(通过 GetLocation 方法检索),并且数组的类型始终保留。 TypeArray 的任何类型符号都有一个基类型(由 GetBaseType 方法返回),该类型的数组是数组的数组。 |
TypeFunction | 函数。 |
TypeTypedef | typedef。 一个模型对象,其类型为 TypeTypedef 的本机类型具有与 typedef 基础的最终类型的规范表示形式完全相同的规范表示形式。 除非使用 IDebugHostType2 的显式 typedef 方法来查询 typedef 信息,否则对象最终用户和类型信息看起来完全透明,或者存在针对 typedef 注册的显式数据模型。 请注意,GetTypeKind 方法永远不会返回 TypeTypedef。 每个方法都将返回 typedef 将返回的最终类型。 IDebugHostType2 上有特定于 typedef 的方法,可用于获取 typedef 特定信息。 |
TypeEnum | 枚举。 一个模型对象,其类型为 TypeEnum 的本机类型具有 ObjectIntrinsic 的规范表示形式,其中内部函数的值和类型与枚举值相同。 |
TypeIntrinsic | 内部函数(基类型)。 一个模型对象,其类型为 TypeIntrinsic 的本机类型具有 ObjectIntrinsic 的规范表示形式。 类型信息可以保留或可能不保留 -- 尤其是基础类型由 IModelObject 中存储的内部数据的变体数据类型(VT_*)完全描述时 |
整体 IDebugHostType2 / IDebugHostType 接口定义如下(不包括 IDebugHostSymbol 方法):
DECLARE_INTERFACE_(IDebugHostType2, IDebugHostType)
{
//
// IDebugHostType:
//
STDMETHOD(GetTypeKind)(_Out_ TypeKind *kind) PURE;
STDMETHOD(GetSize)(_Out_ ULONG64* size) PURE;
STDMETHOD(GetBaseType)(_Out_ IDebugHostType** baseType) PURE;
STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;
STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;
STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;
STDMETHOD(CreatePointerTo)(_In_ PointerKind kind, _COM_Outptr_ IDebugHostType** newType) PURE;
STDMETHOD(GetArrayDimensionality)(_Out_ ULONG64* arrayDimensionality) PURE;
STDMETHOD(GetArrayDimensions)(_In_ ULONG64 dimensions, _Out_writes_(dimensions) ArrayDimension *pDimensions) PURE;
STDMETHOD(CreateArrayOf)(_In_ ULONG64 dimensions, _In_reads_(dimensions) ArrayDimension *pDimensions, _COM_Outptr_ IDebugHostType** newType) PURE;
STDMETHOD(GetFunctionCallingConvention)(_Out_ CallingConventionKind* conventionKind) PURE;
STDMETHOD(GetFunctionReturnType)(_COM_Outptr_ IDebugHostType** returnType) PURE;
STDMETHOD(GetFunctionParameterTypeCount)(_Out_ ULONG64* count) PURE;
STDMETHOD(GetFunctionParameterTypeAt)(_In_ ULONG64 i, _Out_ IDebugHostType** parameterType) PURE;
STDMETHOD(IsGeneric)(_Out_ bool* isGeneric) PURE;
STDMETHOD(GetGenericArgumentCount)(_Out_ ULONG64* argCount) PURE;
STDMETHOD(GetGenericArgumentAt)(_In_ ULONG64 i, _Out_ IDebugHostSymbol** argument) PURE;
//
// IDebugHostType2:
//
STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;
STDMETHOD(GetFunctionVarArgsKind)(_Out_ VarArgsKind* varArgsKind) PURE;
}
IDebugHostType2/IDebugHostType 常规方法
无论 GetTypeKind 方法返回哪种类型,以下 IDebugHostType 方法都是任何类型的一般方法:
STDMETHOD(GetTypeKind)(_Out_ TypeKind *kind) PURE;
STDMETHOD(GetSize)(_Out_ ULONG64* size) PURE;
STDMETHOD(GetBaseType)(_Out_ IDebugHostType** baseType) PURE;
STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
GetTypeKind 方法返回符号引用的类型(指针、数组、内部函数等...)。
GetSize 方法返回类型的大小(就像在 C++ 中已完成 sizeof(type) 一样)。
如果类型是另一种单一类型的派生类型(例如:作为 MyStruct * 派生自 MyStruct'),GetBaseType 方法将返回派生的基类型。 对于指针,这将返回指向的类型。 对于数组,这将返回数组是数组的数组。 如果该类型不是此类派生类型,则返回错误。
GetHashCode 方法返回类型的 32 位哈希代码。 除了全局匹配(例如,等效于 * 的类型签名,如果主机允许的话匹配所有内容),任何可匹配特定类型签名的类型实例都必须返回相同的哈希代码。 此方法与类型签名结合使用,以便将类型签名与类型实例匹配。
IDebugHostType2/IDebugHostType 内部方法
以下 IDebugHostType 方法特定于内部类型(或包含内部数据(如枚举)的类型):
STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;
GetIntrinsicType 方法返回有关类型内部函数类型的信息。 此方法返回两个值:
- 内部类型指示总体类型(例如:整数、无符号、浮点),但不指示类型的大小(例如:8 位、16 位、32 位、64 位)
- 载体类型指示内部类型如何将内部类型打包到 VARIANT 结构中。 这是VT_* 常量。
这两个值的组合提供了有关内部函数的完整信息集。
IDebugHostType2/IDebugHostType Bitfield 方法
以下 IDebugHostType 方法特定于将数据存储在位域的类型。 有关内部函数中的位字段放置的信息作为数据模型中类型符号的一部分存储,而不是作为位置的属性。
STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;
如果数据结构的给定成员是位域(例如:ULONG MyBits:8),则字段的类型信息附带有关位域放置的信息。 GetBitField 方法可用于检索该信息。 此方法在不是位域的任何类型上都将失败。 这是该方法将失败的唯一原因。 只需调用此方法并查看成功/失败即可将位字段与非位字段区分开来。 如果给定类型确实是位字段,则字段位置由半开集 (lsbOfField + lengthOfField : lsbOfField]
IDebugHostType2/IDebugHostType 指针相关方法
以下 IDebugHostType 方法特定于指针类型。 此类类型为 GetTypeKind 返回 TypePointer 或 TypeMemberPointer':
STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;
对于指针类型,GetPointerKind 方法返回指针的类型。 这由 PointerKind 枚举定义。
对于作为指针到成员的类型(如 TypeMemberPointer 类型的指示),GetMemberType 方法返回指针是指向成员的指针的类。
IDebugHostType2/IDebugHostType 数组相关方法
数组是 GetTypeKind 返回 TypeArray 的类型。 请注意,调试主机的类型系统定义的数组与 C 利用的单维零索引、基于零索引的打包线性一维数组不同。 C 样式数组适合定义,但数组的整体范围在 IDebugHostType 中更为广泛。 调试主机中的数组可以是多维的,数组中的每个维度都由名为 ArrayDimensionThis 描述符的描述符定义具有以下字段:
领域 | 含义 |
---|---|
LowerBound | 数组的基本索引作为有符号的 64 位值。 对于 C 样式数组,这始终为零。 它不需要。 数组的单个维度可以考虑从任何 64 位索引开始,甚至从负索引开始。 |
长度 | 数组维度作为无符号 64 位值的长度。 数组的索引跨越半打开集 [LowerBound, LowerBound + Length]。 |
跨 | 定义数组维度的步幅。 对于此维度索引中一个(从 N 到 N + 1)的增加,这表示内存中要向前移动的字节数。 对于 C 样式数组,这将是数组的每个元素的大小。 它不需要。 元素之间的填充可以表示为大于每个元素的大小的步幅。 对于多维数组,此值将指示如何将整个维度向前移动。 请考虑 M x N 矩阵。 这在行主窗体中可能描述为两个维度: |
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]}
或者,也可以以列为主形式描述为两个维度:
{ [LowerBound: 0, Length: M, Stride: sizeof(element)], [LowerBound: 0, Length: N, Stride: M \* sizeof(element)]}
ArrayDimension 概念允许这种灵活性。
以下 IDebugHostType 方法特定于数组类型。
STDMETHOD(GetArrayDimensionality)(\_Out_ ULONG64\* arrayDimensionality) PURE;
STDMETHOD(GetArrayDimensions)(\_In_ ULONG64 dimensions, \_Out_writes_(dimensions) ArrayDimension \*pDimensions) PURE;
GetArrayDimensionality 方法返回数组在其中编制索引的维度数。 对于 C 样式数组,此处返回的值始终为 1。
GetArrayDimensions 方法返回一组描述符,其中一个用于数组的每个维度,如 GetArrayDimensionality 方法指示。 每个描述符都是一个 ArrayDimension 结构,用于描述每个数组维度的起始索引、长度和向前步幅。 这允许描述比 C 类型系统中允许的更强大的数组构造。
对于 C 样式数组,此处返回一个数组维度,其值始终为:
- LowerBound = 0
- Length = ARRAYSIZE(array)
- Stride = sizeof(elementType)
IDebugHostType2/IDebugHostType 函数相关方法
通过一种 TypeFunction 指示它们是函数类型的类型支持 IDebugHostType 和 IDebugHostType2 中的以下方法。
//
// IDebugHostType:
//
STDMETHOD(GetFunctionCallingConvention)(_Out_ CallingConventionKind* conventionKind) PURE;
STDMETHOD(GetFunctionReturnType)(_COM_Outptr_ IDebugHostType** returnType) PURE;
STDMETHOD(GetFunctionParameterTypeCount)(_Out_ ULONG64* count) PURE;
STDMETHOD(GetFunctionParameterTypeAt)(_In_ ULONG64 i, _Out_ IDebugHostType** parameterType) PURE;
//
// IDebugHostType2:
//
STDMETHOD(GetFunctionVarArgsKind)(_Out_ VarArgsKind* varArgsKind) PURE;
GetFunctionCallingConvention 方法返回函数的调用约定。 此类作为 CallingConventionKind 枚举的成员返回。
GetFunctionReturnType 方法返回函数的返回类型。
GetFunctionParameterTypeCount 方法返回函数采用的参数数。 C++ 请注意,此计数中不考虑基于省略号的省略号变量参数标记。 必须通过 GetFunctionVarArgsKind 方法检测此类的存在。 这只会在省略号之前包含参数。
GetFunctionParameterTypeAt 方法将 i-th 参数的类型返回到函数。
GetFunctionVarArgsKind 方法返回给定函数是否使用变量参数列表,如果是,则返回它利用的变量参数样式。 此类定义由 VarArgsKind 枚举的成员定义,如下所示:
枚举 | 含义 |
---|---|
VarArgsNone | 该函数不采用任何变量参数。 |
VarArgsCStyle | 该函数是一个 C 样式 varargs 函数(returnType(arg1, arg2, ...))。函数报告的参数数不包括省略号参数。 传递的任何变量参数在 GetFunctionParameterTypeCount 方法返回的参数数之后发生。 |
IDebugHostType2 GetFunctionVarArgsKind
GetFunctionVarArgsKind 方法返回给定函数是否使用变量参数列表,如果是,则返回它利用的变量参数样式。 此类定义由 VarArgsKind 枚举的成员定义,如下所示:
IDebugHostType2/IDebugHostType Typedef 相关方法
属于 typedef 的任何类型都将像类型是 typedef 基础的最终类型一样。 这意味着 GetTypeKind 等方法不会指示类型为 typedef。 同样,GetBaseType 不会返回定义引用的类型。 相反,它们将指示在 typedef 基础的最终定义上调用它们的行为。 例如:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
PMYSTRUCT 或 PTRMYSTRUCT 的 IDebugHostType 将报告以下信息:
- GetTypeKind 方法将返回 TypePointer。 最终的基础类型 MYSTRUCT * 确实是指针。
- “GetBaseType 方法将返回 MYSTRUCT 的类型。 MYSTRUCT * 的基础类型为 MYSTRUCT。
此处的唯一区别是 IDebugHostType2 上的 typedef 特定方法的行为方式。 这些方法包括:
STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;
在此示例中:
- IsTypedef 方法将为 PMYSTRUCT 和 PTRMYSTRUCT 返回 true
- GetTypedefBaseType 方法将返回 MYSTRUCT * 用于 PMYSTRUCT 和 PTRMYSTRUCT 的 PMYSTRUCT
- GetTypedefFinalBaseType 方法将为这两种类型返回 MYSTRUCT *
IsTypedef 方法是唯一能够查看类型是否为 typedef 的方法。 GetTypeKind 方法的行为将如同对基础类型调用一样。
GetTypedefBaseType 方法将返回 typedef 的直接定义。 在文档中介绍的示例中:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
此方法将为 PTRMYSTRUCT 返回 MYSTRUCT * 和 PMYSTRUCT。
GetTypedefFinalBaseType 方法将返回 typedef 是定义的最终类型。 如果 typedef 是另一个 typedef 的定义,则它将继续遵循定义链,直到它到达的类型不是 typedef,并且将返回该类型。 在文档中介绍的示例中:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
在 PMYSTRUCT 或 PTRMYSTRUCT 上调用时,此方法将返回 MYSTRUCT * 。
IDebugHostType2/IDebugHostType 类型创建方法
STDMETHOD(CreatePointerTo)(_In_ PointerKind kind, _COM_Outptr_ IDebugHostType** newType) PURE;
STDMETHOD(CreateArrayOf)(_In_ ULONG64 dimensions, _In_reads_(dimensions) ArrayDimension *pDimensions, _COM_Outptr_ IDebugHostType** newType) PURE;
常量符号值:IDebugHostConstant
对于符号信息中存在常量值的位置(其中特定值是可能或可能不是常量值的符号),IDebugHostConstant 接口表示此类常量的概念。 这通常用于模板参数等位置,其中给定参数通常是类型,但可能是非类型模板参数(例如:常量)。
IDebugHostConstant 接口的定义如下(忽略 IDebugHostSymbol 实现的泛型方法):
DECLARE_INTERFACE_(IDebugHostConstant, IDebugHostSymbol)
{
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
GetValue 方法返回打包到 VARIANT 中的常量的值。 请务必注意,IDebugHostSymbol 上的 GetType 方法可能会返回常量的特定类型符号。 在这种情况下,不能保证类型符号定义的常量值的打包与此处 GetValue 方法返回的打包相同。
数据成员访问:IDebugHostField
IDebugHostField 类表示一个符号,该符号是类、结构、联合或其他类型构造的数据成员。 它不表示免费数据(例如:全局数据)。 接口的定义如下(忽略 IDebugHostSymbol 的泛型方法):
DECLARE_INTERFACE_(IDebugHostField, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
GetLocationKind 方法根据 LocationKind 枚举返回符号所在的位置类型。 此类枚举可以是以下值之一:
枚举 | 含义 |
---|---|
LocationMember | 该字段是类、结构、联合或其他类型构造的常规数据成员。 它具有相对于包含类型构造的基址的偏移量。 此类基址通常由此指针表示。 可以通过 GetOffset 方法检索字段的偏移量。 对于 LocationMember 的字段,GetLocation 和 GetValue 方法将失败。 |
LocationStatic | 该字段是静态的,具有自己的地址。 GetLocation 方法将返回静态字段的抽象位置(例如:address)。 对于 LocationStatic 字段,GetOffset 和 GetValue 方法将失败。 |
LocationConstant | 该字段是一个常量,具有一个值。 GetValue 方法将返回常量的值。 对于 LocationConstant 字段,GetOffset 和 GetLocation 方法将失败 |
LocationNone | 该字段没有位置。 它可能已由编译器优化,也可能是声明但从未定义的静态字段。 无论这种字段如何出现,它都没有物理存在或价值。 它仅在符号中。 对于 LocationNone 字段,所有获取方法(GetOffset、GetLocation 和 GetValue)都将失败。 |
对于具有偏移量的字段(例如:其位置类型指示 LocationMember 的字段),GetOffset 方法将返回从包含类型(此指针)的基址到字段本身的数据的偏移量。 此类偏移量始终表示为无符号 64 位值。 如果给定字段没有与包含类型的基址相偏移的位置,GetOffset 方法将失败。
对于具有地址的字段,而不考虑特定类型实例(例如:其位置类型指示 LocationStatic 的字段),GetLocation 方法将返回字段的抽象位置(地址)。 如果给定字段没有静态位置,GetLocation 方法将失败。
对于在符号信息中定义的常量值的字段(例如:其位置类型指示 LocationConstant 的字段),GetValue 方法将返回字段的常量值。 如果给定字段没有常量值,GetValue 方法将失败。
免费数据访问:IDebugHostData
不是另一类型的成员的模块中的数据由 IDebugHostData 接口表示。 该接口的定义如下(忽略 IDebugHostSymbol 的泛型方法):
DECLARE_INTERFACE_(IDebugHostData, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
所有这些方法在语义上等效于 IDebugHostField 中的对应项。 唯一的区别是 GetLocationKind 方法永远不会返回 LocationMember 以获取免费数据。
GetLocationKind 方法根据 LocationKind 枚举返回符号所在的位置类型。 可以在 IDebugHostField 的文档中找到此枚举的说明。
对于具有地址的数据,GetLocation 方法将返回字段的抽象位置(address)。 如果给定数据没有静态位置,GetLocation 方法将失败。
对于 datawhich 在符号信息中定义的常量值(例如:其位置类型指示 LocationConstant 的数据),GetValue 方法将返回字段的常量值。 如果给定数据没有常量值,GetValue 方法将失败。
基类:IDebugHostBaseClass
给定类型的继承层次结构通过类型符号的子级表示。 如果给定类型从一个或多个类型派生(继承),则类型符号将有一个或多个 SymbolBaseClass 子级。 每个 SymbolBaseClass 符号都表示特定类型的直接继承。 基类的名称既是 SymbolBaseClass 符号的名称,也是基类的类型符号的名称。 SymbolBaseClass 符号上的 GetType 方法可用于获取基类本身的类型符号。 可以通过以递归方式浏览 SymbolBaseClass 子符号来遍历完整的继承层次结构。 其中每个基类符号都由定义如下的 IDebugHostBaseClass 接口表示(忽略 IDebugHostSymbol 的泛型方法):
DECLARE_INTERFACE_(IDebugHostBaseClass, IDebugHostSymbol)
{
STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
}
GetOffset 方法从派生类的基址返回基类的偏移量。 此类偏移量可以是零,也可能是正无符号 64 位值。
公共符号:IDebugHostPublic
公共符号表示符号文件中公共表中的内容。 实际上,它们是导出地址。 没有与公共符号关联的类型信息 -- 只有一个地址。 除非调用方显式请求公共符号,否则调试主机更喜欢为每个查询返回专用符号。 公共符号由定义如下的 IDebugHostPublic 接口表示(忽略 IDebugHostSymbol 的泛型方法):
DECLARE_INTERFACE_(IDebugHostPublic, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
}
所有这些方法在语义上等效于 IDebugHostField 中的对应项。 唯一的区别是 GetLocationKind 方法永远不会返回此类符号的 LocationMember 或 LocationConstant。
GetLocationKind 方法根据 LocationKind 枚举返回符号所在的位置类型。 可以在 IDebugHostField 的文档中找到此枚举的说明。
对于具有地址的数据,GetLocation 方法将返回字段的抽象位置(address)。 如果给定的公共没有静态位置,GetLocation 方法将失败。
模块签名和版本匹配:IDebugHostModuleSignature
模块签名表示一种检查给定模块是否满足一组有关命名和版本控制的条件的方法。 模块签名是通过 IDebugHostSymbols 上的 CreateModuleSignature 方法创建的。 它可以匹配模块名称,以及模块的可选版本号范围。 创建此类签名后,客户端会收到一个 IDebugHostModuleSignature 接口,该接口定义如下:
DECLARE_INTERFACE_(IDebugHostModuleSignature, IUnknown)
{
STDMETHOD(IsMatch)(_In_ IDebugHostModule* pModule, _Out_ bool* isMatch) PURE;
}
IsMatch 方法将特定模块(由 IDebugHostModule 符号提供)与签名进行比较,将模块名称和版本与签名中指示的名称和版本范围进行比较。 指示给定模块符号是否与签名匹配。
类型签名和类型匹配:IDebugHostTypeSignature
类型签名表示一种检查给定类型实例是否满足一组有关类型名称的条件、类型的泛型参数以及类型所在的模块的方法。 类型签名是通过 IDebugHostSymbols 上的 CreateTypeSignature 方法创建的。 创建此类签名后,客户端会收到一个 IDebugHostTypeSignature 接口,该接口定义如下:
DECLARE_INTERFACE_(IDebugHostTypeSignature, IUnknown)
{
STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
STDMETHOD(IsMatch)(_In_ IDebugHostType* type, _Out_ bool* isMatch, _COM_Outptr_opt_ IDebugHostSymbolEnumerator** wildcardMatches) PURE;
STDMETHOD(CompareAgainst)(_In_ IDebugHostTypeSignature* typeSignature, _Out_ SignatureComparison* result) PURE;
}
GetHashCode 方法返回类型签名的 32 位哈希代码。 调试主机保证类型实例返回的哈希代码与为类型签名返回的哈希代码之间有同步。 除了全局匹配之外,如果类型实例能够匹配类型签名,两者将具有相同的 32 位哈希代码。 这允许在类型实例与向数据模型管理器注册的众多类型签名之间进行初始快速比较和匹配。
IsMatch 方法返回特定类型实例是否与类型签名中指定的条件匹配的指示。 如果确实如此,则返回此指示以及一个枚举器,该枚举器将指示类型实例(作为符号)的所有特定部分,这些部分与类型签名中的通配符匹配。
CompareAgainst 方法将类型签名与另一个类型签名进行比较,并返回两个签名的比较方式。 返回的比较结果是 SignatureComparison 枚举的成员,定义如下:
枚举 | 含义 |
---|---|
不相关的 | 比较的两个签名或类型之间没有关系。 |
模糊 | 一个签名或类型与另一个签名或类型比较不明确。 对于两个类型签名,这意味着可能存在可能匹配任一签名的实例。 例如,下面显示的两种类型签名不明确。 签名 1:std::pair<*, int> 签名 2:std::pair<int,*> ,因为类型实例 std::pair<int, int> 匹配一个相同(两者都具有一个具体匹配项和一个通配符匹配)。 |
LessSpecific | 一个签名或类型比另一个签名或类型更具体。 通常,这意味着不太具体的签名具有通配符,其中更具体的签名具有具体类型。 例如,下面的第一个签名比第二个签名更具体。 签名 1:std::pair<*, int> 签名 2:std::pair<int, int> ,因为它具有通配符(* ),其中第二个具有具体类型(int)。 |
MoreSpecific | 一个签名或类型比另一个签名更具体。 通常,这意味着更具体的签名具有具体类型,其中不太具体的签名具有通配符。 例如,下面的第一个签名比第二个签名更具体。 签名 1:std::pair<int, int> 签名 2:std::pair<*, int> ,因为它具有具体类型(int),其中第二个具有通配符(* )。 |
相同 | 这两个签名或类型是相同的。 |
本主题是一系列教程的一部分,其中介绍了可从C++访问的接口、如何使用它们生成基于C++的调试器扩展,以及如何从C++数据模型扩展中使用其他数据模型构造(例如:JavaScript 或 NatVis)。