Interfaces de C++ del modelo de datos del depurador

En este tema se proporciona información general sobre cómo usar interfaces de C++ del modelo de datos del depurador para ampliar y personalizar las funcionalidades del depurador.

Interfaces de host de C++ del modelo de datos del depurador

Host del modelo de datos del depurador

El modelo de datos del depurador está diseñado para ser un sistema componente que se puede hospedar en una variedad de contextos diferentes. Normalmente, el modelo de datos se hospeda en el contexto de una aplicación del depurador. Para ser un host del modelo de datos, es necesario implementar una serie de interfaces para exponer aspectos básicos del depurador: su destino, sus espacios de memoria, su evaluador, su sistema simbólico y de tipos, etc. Aunque estas interfaces se implementan mediante cualquier aplicación que quiera hospedar el modelo de datos, tanto el modelo de datos principal como cualquier extensión que interopera con el modelo de datos.

El conjunto de interfaces principales son:

Nombre de la interfaz Descripción
IDebugHost Interfaz principal del host de depuración.
IDebugHostStatus Interfaz que permite a un cliente consultar el estado del host.
IDebugHostContext Una abstracción de un contexto dentro del host (por ejemplo: un destino determinado, un proceso determinado, un espacio de direcciones determinado, etc....)
IDebugHostErrorSink Interfaz implementada por los autores de llamadas para recibir errores de determinadas partes del modelo de datos y host
IDebugHostEvaluator / IDebugHostEvaluator2 Evaluador de expresiones del host de depuración.
IDebugHostExtensibility Interfaz para ampliar las funcionalidades del host o partes de él (como el evaluador de expresiones).

El sistema de tipos y las interfaces simbólicas son:

InterfaceName Descripción
IDebugHostSymbols Interfaz principal que proporciona acceso y resolución de símbolos
IDebugHostSymbol / IDebugHostSymbol2 Representa un único símbolo de cualquier tipo. El símbolo concreto es una derivación de esta interfaz.
IDebugHostModule Representa un módulo cargado dentro de un proceso. Se trata de un tipo de símbolo.
IDebugHostType / IDebugHostType2 Representa un tipo de idioma o nativo.
IDebugHostConstant Representa una constante dentro de la información simbólica (por ejemplo: un argumento de plantilla que no es de tipo en C++)
IDebugHostField Representa un campo dentro de una estructura o clase.
IDebugHostData Representa los datos de un módulo (si se tratase de una estructura o clase, sería un IDebugHostField)
IDebugHostBaseClass Representa una clase base.
IDebugHostPublic Representa un símbolo dentro de la tabla publics de una PDB. Esto no tiene información de tipo asociada. Es un nombre y una dirección.
IDebugHostModuleSignature Representa una firma de módulo: una definición que coincidirá con un conjunto de módulos por nombre o versión.
IDebugHostTypeSignature Representa una firma de tipo: una definición que coincidirá con un conjunto de tipos por módulo o nombre.

Interfaz de host principal: IDebugHost

La interfaz IDebugHost es la interfaz principal de cualquier host de modelo de datos. Se define de la manera siguiente:

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

El método GetHostDefinedInterface devuelve la interfaz privada principal del host, si existe para el host determinado. En herramientas de depuración para Windows, la interfaz devuelta aquí es IDebugClient (conversión a IUnknown).

GetCurrentContext

El método GetCurrentContext devuelve una interfaz que representa el estado actual del host del depurador. El significado exacto de esto se deja en el host, pero normalmente incluye elementos como la sesión, el proceso y el espacio de direcciones que está activo en la interfaz de usuario del host de depuración. El objeto de contexto devuelto es en gran medida opaco para el autor de la llamada, pero es un objeto importante pasar entre llamadas al host de depuración. Cuando un llamador es, por ejemplo, leer la memoria, es importante saber desde qué proceso y espacio de direcciones se lee la memoria. Esa noción se encapsula en la noción del objeto de contexto que se devuelve de este método.

GetDefaultMetadata

El método GetDefaultMetadata devuelve un almacén de metadatos predeterminado que se puede usar para determinadas operaciones (por ejemplo: conversión de cadena) cuando no se han pasado metadatos explícitos. Esto permite que el host de depuración tenga algún control sobre la forma en que se presentan algunos datos. Por ejemplo, los metadatos predeterminados pueden incluir una clave PreferredRadix, lo que permite al host indicar si los ordinales deben mostrarse en decimal o hexadecimal si no se especifica de otro modo.

Tenga en cuenta que los valores de propiedad del almacén de metadatos predeterminados deben resolverse manualmente y deben pasar el objeto para el que se consultan los metadatos predeterminados. El método GetKey debe usarse en lugar de GetKeyValue.

Interfaz de estado: IDebugHostStatus

La interfaz IDebugHostStatus permite que un cliente del modelo de datos o el host de depuración pregunten sobre ciertos aspectos del estado del host de depuración. La interfaz se define de la siguiente manera:

DECLARE_INTERFACE_(IDebugHostStatus, IUnknown)
{
    STDMETHOD(PollUserInterrupt)(_Out_ bool* interruptRequested) PURE;
}

PollUserInterrupt

El método PollUserInterrupt se usa para preguntar si el usuario del host de depuración ha solicitado una interrupción de la operación actual. Un descriptor de acceso de propiedad en el modelo de datos puede, por ejemplo, llamar a código arbitrario (por ejemplo: un método de JavaScript). Ese código puede tardar un tiempo arbitrario. Para mantener la capacidad de respuesta del host de depuración, cualquier código que pueda tardar un tiempo arbitrario debe comprobar si hay una solicitud de interrupción mediante una llamada a este método. Si el valor interruptRequested vuelve como true, el autor de la llamada debe anular inmediatamente y devolver un resultado de E_ABORT.

Interfaz de contexto: IDebugHostContext

El contexto es uno de los aspectos más importantes del modelo de datos y el host de depuración subyacente. Al contener un objeto, es importante poder saber de dónde procede un objeto, en qué proceso se encuentra, con qué espacio de direcciones está asociado. Conocer esta información permite la interpretación correcta de cosas como los valores de puntero. Un objeto del tipo IDebugHostContext debe pasarse a muchos métodos en el host de depuración. Esta interfaz se puede adquirir de varias maneras:

  • Obteniendo el contexto actual del depurador: llamando al método GetCurrentContext de IDebugHost
  • Obteniendo el contexto de un objeto: llamando al método GetContext de IModelObject
  • Obteniendo el contexto de un símbolo: llamando al método GetContext de IDebugHostSymbol

Además, hay dos valores que tienen un significado especial en el contexto de una interfaz IDebugHostContext que se devuelve o se pasa a un modelo de datos o a un método host de depuración:

nullptr: indica que no hay ningún contexto. Es perfectamente válido para que algunos objetos no tengan contexto. El objeto Debugger del espacio de nombres raíz del modelo de datos no hace referencia a nada dentro de un proceso o espacio de direcciones específico. No tiene contexto.

USE_CURRENT_HOST_CONTEXT: un valor centinela que indica que debe usar el contexto de interfaz de usuario actual del host de depuración. Este valor nunca se devolverá desde el host de depuración. Sin embargo, puede pasarse a cualquier método host de depuración que tome una entrada IDebugHostContext en lugar de llamar explícitamente al método GetCurrentContext de IDebugHost. Tenga en cuenta que pasar explícitamente USE_CURRENT_HOST_CONTEXT suele ser más eficaz que obtener explícitamente el contexto actual.

Los contextos de un contexto de host son en gran medida opacos para el autor de la llamada. La única operación que un autor de la llamada fuera del host de depuración principal puede hacer con un contexto de host es compararlo con otro contexto de host.

La interfaz IDebugHostContext se define de la siguiente manera:

DECLARE_INTERFACE_(IDebugHostContext, IUnknown)
{
    STDMETHOD(IsEqualTo)(_In_ IDebugHostContext *pContext, _Out_ bool *pIsEqual) PURE;
}

IsEqualTo

El método IsEqualTo compara un contexto de host con otro contexto de host. Si los dos contextos son equivalentes, se devuelve una indicación de esto. Tenga en cuenta que esta comparación no es equivalencia de interfaz. Esto compara el contenido opaco subyacente del propio contexto.

El receptor de errores: IDebugHostErrorSink

IDebugHostErrorSink es un medio por el que un cliente puede recibir notificaciones de errores que se producen durante determinadas operaciones y enrutar esos errores cuando sea necesario. La interfaz se define de la siguiente manera:

enum ErrorClass
{
    ErrorClassWarning,
    ErrorClassError
}
DECLARE_INTERFACE_(IDebugHostErrorSink, IUnknown)
{
    STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrError, _In_ PCWSTR message) PURE;
}

ReportError

El método ReportError es una devolución de llamada en el receptor de errores para notificarle que se ha producido un error y permitir que el receptor enrute el error a cualquier interfaz de usuario o mecanismo que sea adecuado.

Evaluador de host: IDebugHostEvaluator / IDebugHostEvaluator2

Una de las partes más importantes de la funcionalidad que proporciona el host de depuración a los clientes es el acceso a su evaluador de expresiones basadas en lenguaje. Las interfaces IDebugHostEvaluator e IDebugHostEvaluator2 son los medios para acceder a esa funcionalidad desde el host de depuración.

Las interfaces se definen de la siguiente manera:

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

El método EvaluateExpression permite que el host de depuración evalúe una expresión de lenguaje (por ejemplo, C++) y devuelva el valor resultante de esa evaluación de expresión boxing como IModelObject. Esta variante concreta del método solo permite construcciones de lenguaje. Cualquier funcionalidad adicional que se presente en el evaluador de expresiones del host de depuración que no esté presente en el lenguaje (por ejemplo: métodos de consulta LINQ) está desactivada para la evaluación.

EvaluateExtendedExpression

El método EvaluateExtendedExpression es similar al método EvaluateExpression, salvo que vuelve a activar la funcionalidad adicional que no es de lenguaje que un host de depuración determinado elige agregar a su evaluador de expresiones. En herramientas de depuración para Windows, por ejemplo, esto habilita tipos anónimos, consultas LINQ, calificadores de módulo, especificadores de formato y otras funciones que no son de C/C++.

IDebugHostEvaluator2

AssignTo

El método AssignTo realiza la asignación según la semántica del lenguaje que se está depurando.

Interfaz de extensibilidad de host: IDebugHostExtensibility

Cierta funcionalidad del host de depuración está opcionalmente sujeta a extensibilidad. Esto puede incluir, por ejemplo, el evaluador de expresiones. La interfaz IDebugHostExtensibility es el medio por el que se accede a estos puntos de extensibilidad. La interfaz se define de la siguiente manera:

DECLARE_INTERFACE_(IDebugHostExtensibility, IUnknown)
{
    STDMETHOD(CreateFunctionAlias)(_In_ PCWSTR aliasName, _In_ IModelObject *functionObject) PURE;
    STDMETHOD(DestroyFunctionAlias)(_In_ PCWSTR aliasName) PURE;
}

CreateFunctionAlias

El método CreateFunctionAlias crea un "alias de función", un "alias rápido" para un método implementado en alguna extensión. El significado de este alias es específico del host. Puede extender el evaluador de expresiones del host con la función o puede hacer algo completamente diferente.

DestroyFunctionAlias

El método DestroyFunctionAlias deshace una llamada anterior al método CreateFunctionAlias. La función ya no estará disponible en el nombre de alias rápido.

Acceso al modelo de datos

En primer lugar, las API de extensibilidad del modelo de datos están diseñadas para ser neutrales para la aplicación (normalmente un depurador) que actúa como host del modelo de datos. En teoría, cualquier aplicación puede hospedar el modelo de datos proporcionando un conjunto de API de host que exponen el sistema de tipos de los destinos de depuración de la aplicación y un conjunto de objetos proyectados en el espacio de nombres del modelo de datos sobre qué destinos, procesos, subprocesos, etc. están en esos destinos de depuración.

Aunque las API del modelo de datos (las que comienzan IDataModel, IDebugHost y las salidas de IModelObject) están diseñadas para ser portátiles, no definen lo que es una "extensión del depurador". En la actualidad, un componente que desea ampliar las herramientas de depuración para Windows y el motor que proporciona debe escribir una extensión de motor para obtener acceso al modelo de datos. Esa extensión del motor solo debe ser una extensión de motor tanto como ese es el mecanismo de carga y arranque de la extensión. Por lo tanto, una implementación mínima proporcionaría:

  • DebugExtensionInitialize: un método que utiliza un IDebugClient creado para obtener acceso al modelo de datos y configurar manipulaciones del modelo de objetos.
  • DebugExtensionUninitialize: método que deshace las manipulaciones del modelo de objetos que se realizaron en DebugExtensionInitialize.
  • DebugExtensionCanUnload: método que devuelve si la extensión puede descargarse. Si todavía hay objetos COM activos en la extensión, debe indicarlo. Este es el equivalente del depurador de DllCanUnloadNow de COM. Si devuelve el S_FALSE indicación de incapacidad de descargar, el depurador puede consultarlo más adelante para ver si una descarga es segura o puede reinicializar la extensión llamando de nuevo a DebugExtensionInitialize. La extensión debe estar preparada para controlar ambas rutas de acceso.
  • DebugExtensionUnload: un método que realiza cualquier limpieza final necesaria justo antes de que se descargue la DLL.

Interfaz bridge: IHostDataModelAccess

Como se mencionó, cuando se llama a DebugExtensionInitialize, crea un cliente de depuración y obtiene acceso al modelo de datos. Este acceso se proporciona mediante una interfaz de puente entre las interfaces IDebug* heredadas de Herramientas de depuración para Windows y el modelo de datos. Esta interfaz de puente es "IHostDataModelAccess" y se define de la siguiente manera:

DECLARE_INTERFACE_(IHostDataModelAccess, IUnknown)
{
   STDMETHOD(GetDataModel)(_COM_Outptr_ IDataModelManager** manager, _COM_Outptr_ IDebugHost** host) PURE;
}

GetDataModel

El método GetDataModel es el método de la interfaz bridge que proporciona acceso a ambos lados del modelo de datos: el host de depuración (el borde inferior del depurador) se expresa mediante la interfaz IDebugHost devuelta El componente principal del modelo de datos: el administrador de modelos de datos se expresa mediante la interfaz IDataModelManager devuelta.

Interfaces del sistema del modelo de datos del depurador

Host del modelo de datos

El modelo de datos del depurador está diseñado para ser un sistema componente que se puede hospedar en una variedad de contextos diferentes. Normalmente, el modelo de datos se hospeda en el contexto de una aplicación del depurador. Para ser un host del modelo de datos, es necesario implementar varias interfaces para exponer aspectos básicos del depurador: su destino, sus espacios de memoria, su evaluador, su sistema simbólico y de tipos, etc. Aunque cualquier aplicación que desee hospedar el modelo de datos implementa estas interfaces, tanto el modelo de datos principal como cualquier extensión que interopera con el modelo de datos.

El sistema de tipos y las interfaces simbólicas son:

Nombre de la interfaz Descripción
IDebugHostSymbols Interfaz principal que proporciona acceso y resolución de símbolos
IDebugHostSymbol/ IDebugHostSymbol2 Representa un único símbolo de cualquier tipo. El símbolo concreto es una derivación de esta interfaz.
IDebugHostModule Representa un módulo cargado dentro de un proceso. Se trata de un tipo de símbolo.
IDebugHostType/IDebugHostType2 Representa un tipo de idioma o nativo.
IDebugHostConstant Representa una constante dentro de la información simbólica (por ejemplo: un argumento de plantilla que no es de tipo en C++)
IDebugHostField Representa un campo dentro de una estructura o clase.
IDebugHostData Representa los datos de un módulo (si se trata de una estructura o clase, sería un IDebugHostField)
IDebugHostBaseClass Representa una clase base.
IDebugHostPublic Representa un símbolo dentro de la tabla publics de una PDB. Esto no tiene información de tipo asociada. Es un nombre y una dirección.
IDebugHostModuleSignature Representa una firma de módulo: una definición que coincidirá con un conjunto de módulos por nombre o versión.
IDebugHostTypeSignature Representa una firma de tipo: una definición que coincidirá con un conjunto de tipos por módulo o nombre.

Las otras interfaces principales son:

Nombre de la interfaz Descripción
IDebugHost Interfaz principal del host de depuración.
IDebugHostStatus Interfaz que permite a un cliente consultar el estado del host.
IDebugHostContext Abstracción de un contexto dentro del host (por ejemplo: un destino determinado, un proceso determinado, un espacio de direcciones determinado, etc....)
IDebugHostErrorSink Una interfaz implementada por los autores de llamadas para recibir errores de determinadas partes del host y el modelo de datos
IDebugHostEvaluator / IDebugHostEvaluator2 Evaluador de expresiones del host de depuración.
IDebugHostExtensibility Interfaz para ampliar las funcionalidades del host o partes de él (como el evaluador de expresiones).

La interfaz simbólica principal: IDebugHostSymbols

La interfaz IDebugHostSymbols es el punto de partida principal para acceder a los símbolos del destino de depuración. Esta interfaz se puede consultar desde una instancia de IDebugHost y se define de la siguiente manera:

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

El método CreateModuleSignature crea una firma que se puede usar para que coincida con un conjunto de módulos específicos por nombre y, opcionalmente, por versión. Hay tres componentes en una firma de módulo:

  • Un nombre: un módulo coincidente debe tener un nombre que sea una coincidencia exacta que no distingue mayúsculas de minúsculas con el nombre de la firma.
  • Una versión mínima: si se especifica, un módulo coincidente debe tener una versión mínima que sea al menos tan alta como esta versión. Las versiones se especifican en formato "A.B.C.D" y cada parte posterior es menos importante que la anterior. Solo el primer segmento es obligatorio.
  • Una versión máxima: si se especifica, un módulo coincidente debe tener una versión máxima que no sea superior a esta versión. Las versiones se especifican en formato "A.B.C.D" y cada parte posterior es menos importante que la anterior. Solo el primer segmento es obligatorio.

CreateTypeSignature

El método CreateTypeSignature crea una firma que se puede usar para buscar coincidencias con un conjunto de tipos concretos mediante el uso de un módulo y un nombre de tipo. El formato de la cadena de firma de nombre de tipo es específico del lenguaje que se está depurando (y del host de depuración). Para C/C++, la cadena de firma es equivalente a una especificación de tipo NatVis. Es decir, la cadena de firma es un nombre de tipo donde se permiten caracteres comodín (especificados como *) para argumentos de plantilla.

CreateTypeSignatureForModuleRange

El método CreateTypeSignatureForModuleRange crea una firma que se puede usar para hacer coincidir un conjunto de tipos concretos mediante la firma del módulo y el nombre de tipo. Esto es similar al método CreateTypeSignature, excepto que, en lugar de pasar un módulo específico para que coincida con la firma, el autor de la llamada pasa los argumentos necesarios para crear una firma de módulo (como si la firma del módulo se creara con el método CreateModuleSignature).

EnumerateModules

El método EnumerateModules crea un enumerador que enumerará todos los módulos disponibles en un contexto de host determinado. Ese contexto de host podría encapsular un contexto de proceso o podría encapsular algo parecido al kernel de Windows.

FindModuleByName

El método FindModuleByName buscará en el contexto de host especificado y buscará un módulo que tenga el nombre especificado y devolverá una interfaz a él. Es legal buscar el módulo por nombre con o sin la extensión de archivo.

FindModuleByLocation

El método FindModuleByLocation examinará el contexto de host especificado y determinará qué módulo contiene la dirección especificada por la ubicación especificada. A continuación, devolverá una interfaz a este módulo.

GetMostDerivedObject

GetMostDerivedObject usará el sistema de tipos del depurador para determinar el tipo en tiempo de ejecución de un objeto a partir de su tipo estático. Este método solo usará información simbólica y heurística disponibles en la capa del sistema de tipos para realizar este análisis. Esta información puede incluir RTTI de C++ (información de tipo de tiempo de ejecución) o análisis de la forma de las tablas de funciones virtuales del objeto. No incluye elementos como el concepto de tipo en tiempo de ejecución preferido en un IModelObject. Si el análisis no encuentra un tipo en tiempo de ejecución o no encuentra un tipo en tiempo de ejecución diferente del tipo estático pasado al método , se puede pasar la ubicación de entrada y el tipo. No se producirá un error en el método por estos motivos.

Interfaz de símbolo individual principal: IDebugHostSymbol

Todos los símbolos que se pueden devolver desde el host del modelo de datos se derivarán de alguna manera de IDebugHostSymbol. Esta es la interfaz principal que cada símbolo implementa independientemente del tipo de símbolo. En función del tipo de símbolo, un símbolo determinado puede implementar un conjunto de otras interfaces que devuelvan atributos más únicos para el tipo de símbolo determinado representado por esta interfaz. La interfaz IDebugHostSymbol2 / IDebugHostSymbol se define de la siguiente manera:

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;
}

Es muy importante tener en cuenta que esta interfaz representa muchos tipos de símbolos, delineados por la enumeración SymbolKind, que tiene valores como se indica a continuación:

Enumarant Significado
Símbolo Tipo de símbolo no especificado
SymbolModule El símbolo es un módulo y se puede consultar para IDebugHostModule.
SymbolType El símbolo es un tipo y se puede consultar para IDebugHostType.
SymbolField El símbolo es un campo (un miembro de datos dentro de una estructura o clase) y se puede consultar para IDebugHostField.
SymbolConstant El símbolo es un valor constante y se puede consultar para IDebugHostConstant.
SymbolData El símbolo es datos que no son miembros de una estructura o clase y son consultables para IDebugHostData.
SymbolBaseClass El símbolo es una clase base y es consultable para IDebugHostBaseClass
SymbolPublic El símbolo es una entrada en la tabla publics de un módulo (sin información de tipo) y es consultable para IDebugHostPublic.
SymbolFunction El símbolo es una función y es consultable para IDebugHostData

GetContext

El método GetContext devuelve el contexto donde el símbolo es válido. Aunque esto representará cosas como el destino de depuración y el espacio de direcciones o proceso en el que existe el símbolo, puede que no sea tan específico como un contexto recuperado de otros medios (por ejemplo: de un IModelObject).

EnumerateChildren

El método EnumerateChildren devuelve un enumerador que enumerará todos los elementos secundarios de un símbolo determinado. Para un tipo de C++, por ejemplo, las clases base, los campos, las funciones miembro y el tipo se consideran elementos secundarios del símbolo de tipo.

Interfaz del módulo: IDebugHostModule

La noción del depurador de un módulo que se carga dentro de algún espacio de direcciones se representa de dos maneras distintas en el modelo de datos: en el nivel de sistema de tipo a través de la interfaz IDebugHostModule. En este caso, un módulo es un símbolo y los atributos principales del módulo son llamadas a métodos de interfaz proyectados en el nivel de modelo de datos a través del modelo de datos Debugger.Models.Module. Se trata de una encapsulación extensible del sistema de tipos IDebugHostModule representación de un módulo.

La interfaz IDebugHostModule se define de la siguiente manera (omitiendo los métodos genéricos de 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

El método GetImageName devuelve el nombre de la imagen del módulo. Según el valor del argumento allowPath, el nombre de imagen devuelto puede incluir o no la ruta de acceso completa a la imagen.

GetBaseLocation

El método GetBaseLocation devuelve la dirección de carga base del módulo como una estructura de ubicación. La estructura de ubicación devuelta para un módulo normalmente hará referencia a una dirección virtual.

GetVersion

El método GetVersion devuelve información de versión sobre el módulo (suponiendo que dicha información se pueda leer correctamente fuera de los encabezados). Si se solicita una versión determinada (a través de un puntero de salida que no es nullptr) y no se puede leer, se devolverá un código de error adecuado desde la llamada al método.

FindTypeByName

El método FindTypeByName busca un tipo definido en el módulo por el nombre de tipo y devuelve un símbolo de tipo para él. Este método puede devolver un IDebugHostType válido que nunca se devolvería a través de la recursividad explícita de los elementos secundarios del módulo. El host de depuración puede permitir la creación de tipos derivados: tipos que no se usan nunca dentro del propio módulo, sino derivados de tipos que son. Por ejemplo, si la estructura MyStruct se define en los símbolos del módulo, pero el tipo MyStruct ** nunca se usa, el método FindTypeByName puede devolver legítimamente un símbolo de tipo para MyStruct ** a pesar de que ese nombre de tipo nunca aparece explícitamente en los símbolos del módulo.

FindSymbolByRVA

El método FindSymbolByRVA encontrará un único símbolo coincidente en la dirección virtual relativa especificada dentro del módulo. Si no hay un solo símbolo en la RVA proporcionada (por ejemplo, hay varias coincidencias), este método devolverá un error. Tenga en cuenta que este método prefiere devolver un símbolo privado sobre un símbolo de la tabla pública.

FindSymbolByName

El método FindSymbolByName encontrará un único símbolo global del nombre especificado en el módulo. Si no hay un único símbolo que coincida con el nombre especificado, este método devolverá un error. Tenga en cuenta que este método prefiere devolver un símbolo privado sobre un símbolo de la tabla pública.

Acceso al sistema de tipos: IDebugHostType2 / IDebugHostType

Un idioma o tipo nativo determinado se describe mediante las interfaces IDebugHostType2 o IDebugHostType. Tenga en cuenta que algunos de los métodos de estas interfaces solo se aplican a tipos específicos de tipos. Un símbolo de tipo determinado puede hacer referencia a uno de los siguientes tipos, tal como se describe en la enumeración TypeKind:

Tipo Descripción
TypeUDT Un tipo definido por el usuario (una estructura, clase, unión, etc.). Objeto de modelo que tiene un tipo nativo cuyo tipo es TypeUDT tiene una representación canónica de ObjectTargetObject donde el tipo siempre se mantiene dentro del IModelObject correspondiente.
TypePointer Puntero. Objeto de modelo que tiene un tipo nativo cuyo tipo es TypePointer tiene una representación canónica de ObjectIntrinsic donde el valor del puntero es cero se extiende a VT_UI8 y se mantiene como datos intrínsecos en este formulario de 64 bits. Cualquier símbolo de tipo de TypePointer tiene un tipo base (tal como lo devuelve el método GetBaseType) del tipo al que apunta el puntero.
TypeMemberPointer Puntero al miembro de clase. Objeto de modelo que tiene un tipo nativo cuyo tipo es TypeMemberPointer tiene una representación canónica que es intrínseca (el valor es el mismo que el valor de puntero). El significado exacto de este valor es específico del host de compilación o depuración.
TypeArray Matriz . Objeto de modelo que tiene un tipo nativo cuyo tipo es TypeArray tiene una representación canónica de ObjectTargetObject. La dirección base de la matriz es la ubicación del objeto (recuperada a través del método GetLocation) y el tipo de la matriz siempre se mantiene. Cualquier símbolo de tipo de TypeArray tiene un tipo base (tal como lo devuelve el método GetBaseType) del tipo del que la matriz es una matriz de .
TypeFunction Función.
TypeTypedef Definición de tipo. Un objeto de modelo que tiene un tipo nativo cuyo tipo sería TypeTypedef tiene una representación canónica idéntica a la representación canónica del tipo final subyacente a la definición de tipo. Esto aparece completamente transparente para el usuario final del objeto y la información de tipo a menos que los métodos typedef explícitos de IDebugHostType2 se utilicen para consultar información de typedef o hay un modelo de datos explícito registrado en la definición de tipo. Tenga en cuenta que el método GetTypeKind nunca devolverá TypeTypedef. Cada método devolverá lo que devolvería el tipo final subyacente a la definición de tipo. Hay métodos específicos typedef en IDebugHostType2 que se pueden usar para obtener la información específica de typedef.
TypeEnum Una enumeración. Objeto de modelo que tiene un tipo nativo cuyo tipo es TypeEnum tiene una representación canónica de ObjectIntrinsic donde el valor y el tipo del intrínseco son idénticos al valor de enumeración.
TypeIntrinsic Intrínseco (tipo base). Objeto de modelo que tiene un tipo nativo cuyo tipo es TypeIntrinsic tiene una representación canónica de ObjectIntrinsic. La información de tipo puede o no mantenerse, especialmente si el tipo subyacente está totalmente descrito por el tipo de datos variant (VT_*) de los datos intrínsecos almacenados en IModelObject

La interfaz IDebugHostType2 / IDebugHostType general se define como se indica a continuación (excepto los métodos 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;
}

Métodos generales IDebugHostType2/IDebugHostType

Los métodos IDebugHostType siguientes son generales para cualquier tipo, independientemente de qué tipo se devuelva desde el método GetTypeKind:

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

El método GetTypeKind devuelve a qué tipo de tipo (puntero, matriz, intrínseco, etc.) se refiere el símbolo.

GetSize

El método GetSize devuelve el tamaño del tipo (como si hubiera hecho sizeof(type) en C++).

GetBaseType

Si el tipo es un derivado de otro tipo único (por ejemplo: como MyStruct * se deriva de MyStruct'), el método GetBaseType devuelve el tipo base de la derivación. En el caso de los punteros, devuelve el tipo al que apunta. En el caso de las matrices, esto devuelve lo que la matriz es una matriz de . Si el tipo no es de este tipo derivado, se devuelve un error.

GetHashCode

El método GetHashCode devuelve un código hash de 32 bits para el tipo. Con la excepción de una coincidencia global (por ejemplo, una firma de tipo equivalente a * que coincide con todo si el host lo permite), cualquier instancia de tipo que pueda coincidir con una firma de tipo determinada debe devolver el mismo código hash. Este método se usa junto con las firmas de tipo para hacer coincidir las firmas de tipo con las instancias de tipo.

Métodos intrínsecos IDebugHostType2/IDebugHostType

Los métodos IDebugHostType siguientes son específicos de los tipos intrínsecos (o tipos que contienen datos intrínsecos como enumeraciones):

STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;

GetIntrinsicType

El método GetIntrinsicType devuelve información sobre qué tipo de intrínseco es el tipo. Se devuelven dos valores fuera de este método:

  • El tipo intrínseco indica el tipo general (por ejemplo: entero, sin signo, punto flotante), pero no el tamaño del tipo (por ejemplo: 8 bits, 16 bits, 32 bits, 64 bits)
  • El tipo portador indica cómo el tipo intrínseco se empaqueta en una estructura VARIANT. Se trata de una constante VT_*.

La combinación de los dos valores proporciona el conjunto completo de información sobre el intrínseco.

Métodos bitfield de IDebugHostType2/IDebugHostType

Los siguientes métodos IDebugHostType son específicos de los tipos que almacenan datos en campos de bits. La información sobre la ubicación del campo de bits dentro de un intrínseco se almacena como parte del símbolo de tipo en el modelo de datos en lugar de ser un atributo de la ubicación.

STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;

GetBitField

Si un miembro determinado de una estructura de datos es un campo de bits (por ejemplo: ULONG MyBits:8), la información de tipo del campo lleva información sobre la ubicación del campo de bits. El método GetBitField se puede usar para recuperar esa información. Este método producirá un error en cualquier tipo que no sea un campo de bits. Esta es la única razón por la que se producirá un error en el método. Simplemente llamar a este método y examinar el éxito o el error es suficiente para distinguir un campo de bits de un campo que no es de bits. Si un tipo determinado es un campo de bits, las posiciones de campo se definen mediante el conjunto de apertura medio (lsbOfField + lengthOfField : lsbOfField]

Métodos relacionados con el puntero IDebugHostType2/IDebugHostType

Los siguientes métodos IDebugHostType son específicos de los tipos de puntero. Estos son los tipos en los que GetTypeKind devuelve TypePointer o TypeMemberPointer':

STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;

GetPointerKind

Para los tipos que son punteros, el método GetPointerKind devuelve el tipo de puntero. Esto se define mediante la enumeración PointerKind.

GetMemberType

Para los tipos que son de puntero a miembro (como se indica en un tipo de TypeMemberPointer), el método GetMemberType devuelve la clase de la que el puntero es un puntero a miembro.

Métodos relacionados con la matriz IDebugHostType2/IDebugHostType

Las matrices son tipos donde GetTypeKind devuelve TypeArray. Tenga en cuenta que las matrices definidas por el sistema de tipos del host de depuración no son las mismas que las matrices unidimensionales, basadas en índice cero, agrupadas matrices unidimensionales lineales que C utiliza. Las matrices de estilo C encajan en la definición, pero el ámbito general de una matriz es más amplio en IDebugHostType. Una matriz del host de depuración puede ser multidimensional y cada dimensión de la matriz se define mediante un descriptor conocido como ArrayDimensionThis que tiene los siguientes campos:

Campo Significado
LowerBound Índice base de la matriz como un valor de 64 bits con signo. Para una matriz de estilo C, siempre será cero. No es necesario. Se puede considerar que una dimensión individual de una matriz se inicia en cualquier índice de 64 bits, incluso en un negativo.
Length Longitud de la dimensión de matriz como un valor de 64 bits sin signo. Las indicciones de la matriz abarcan el conjunto medio abierto [LowerBound, LowerBound + Length).
Intervalo Define el intervalo de la dimensión de matriz. Para un aumento de uno (de N a N + 1) en el índice de esta dimensión, esto indica cuántos bytes se van a avanzar en la memoria. Para una matriz de estilo C, este sería el tamaño de cada elemento de la matriz. No es necesario. El relleno entre elementos se puede expresar como un paso mayor que el tamaño de cada elemento individual. En el caso de las matrices multidimensionales, este valor indicaría cómo mover una dimensión completa hacia delante. Considere una matriz M x N. Esto puede describirse en forma principal de fila como dos dimensiones:
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]} 

o bien, también se puede describir en forma principal de columna como dos dimensiones:

{ [LowerBound: 0, Length: M, Stride: sizeof(element)], [LowerBound: 0, Length: N, Stride: M \* sizeof(element)]} 

El concepto ArrayDimension permite este grado de flexibilidad.

Los métodos IDebugHostType siguientes son específicos de los tipos de matriz.

STDMETHOD(GetArrayDimensionality)(\_Out_ ULONG64\* arrayDimensionality) PURE; 
STDMETHOD(GetArrayDimensions)(\_In_ ULONG64 dimensions, \_Out_writes_(dimensions) ArrayDimension \*pDimensions) PURE;

GetArrayDimensionality

El método GetArrayDimensionality devuelve el número de dimensiones en las que se indiza la matriz. Para las matrices de estilo C, el valor devuelto aquí siempre será 1.

GetArrayDimensions

El método GetArrayDimensions devuelve un conjunto de descriptores, uno para cada dimensión de la matriz, como se indica en el método GetArrayDimensionality. Cada descriptor es una estructura ArrayDimension que describe el índice inicial, la longitud y el paso hacia delante de cada dimensión de matriz. Esto permite descripciones de construcciones de matriz significativamente más eficaces de las permitidas en el sistema de tipos de C.

Para las matrices de estilo C, se devuelve una sola dimensión de matriz aquí con valores que siempre son:

  • LowerBound = 0
  • Length = ARRAYSIZE(array)
  • Stride = sizeof(elementType)

Métodos relacionados con la función IDebugHostType2/IDebugHostType

Los tipos que indican que son tipos de función a través de un tipo de TypeFunction admiten los métodos siguientes en IDebugHostType e 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

El método GetFunctionCallingConvention devuelve la convención de llamada de la función. Se devuelve como miembro de la enumeración CallingConventionKind.

GetFunctionReturnType

El método GetFunctionReturnType devuelve el tipo de valor devuelto de la función.

GetFunctionParameterTypeCount

El método GetFunctionParameterTypeCount devuelve el número de argumentos que toma la función. Tenga en cuenta que el marcador de argumento de variable basado en puntos suspensivos de C/C++ no se considera en este recuento. La presencia de este tipo debe detectarse a través del método GetFunctionVarArgsKind. Esto solo incluirá argumentos antes de los puntos suspensivos.

GetFunctionParameterTypeAt

El método GetFunctionParameterTypeAt devuelve el tipo del argumento i-th a la función.

El método GetFunctionVarArgsKind devuelve si una función determinada utiliza una lista de argumentos de variable y, si es así, qué estilo de argumentos de variable utiliza. Tal se define mediante un miembro de la enumeración VarArgsKind definida como se indica a continuación:

Enumerant Significado
VarArgsNone La función no toma ningún argumento de variable.
VarArgsCStyle La función es una función varargs de estilo C (returnType(arg1, arg2, ...)). El número de argumentos notificados por la función no incluye el argumento de puntos suspensivos. Cualquier paso de argumentos de variable se produce después del número de argumentos devueltos por el método GetFunctionParameterTypeCount.

IDebugHostType2 GetFunctionVarArgsKind

El método GetFunctionVarArgsKind devuelve si una función determinada utiliza una lista de argumentos de variable y, si es así, qué estilo de argumentos de variable utiliza. Tal se define mediante un miembro de la enumeración VarArgsKind definida como se indica a continuación:

Métodos relacionados con la definición de tipo IDebugHostType2/IDebugHostType

Cualquier tipo que sea una definición de tipo se comportará como si el tipo fuera el tipo final subyacente a la definición de tipo. Esto significa que los métodos como GetTypeKind no indicarán que el tipo es una definición de tipo. Del mismo modo, GetBaseType no devolverá el tipo al que hace referencia la definición. En su lugar, indicarán que se comportan como si se llamaran en la definición final subyacente a la definición de tipo. Por ejemplo:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

Un IDebugHostType para "PMYSTRUCT o PTRMYSTRUCT notificará la siguiente información:

  • El método GetTypeKind devolverá TypePointer. El tipo subyacente final MYSTRUCT * es realmente un puntero.
  • El método 'GetBaseType devolverá un tipo para MYSTRUCT. El tipo subyacente de MYSTRUCT * es MYSTRUCT.

La única diferencia aquí es cómo se comportan los métodos específicos typedef en IDebugHostType2. Estos métodos son:

STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;

En este ejemplo:

  • El método IsTypedef devolverá true para PMYSTRUCT y PTRMYSTRUCT.
  • El método GetTypedefBaseType devolverá MYSTRUCT * para PMYSTRUCT y PMYSTRUCT para PTRMYSTRUCT.
  • El método GetTypedefFinalBaseType devolverá MYSTRUCT * para ambos tipos.

IsTypedef

El método IsTypedef es el único método capaz de ver si un tipo es una definición de tipo. El método GetTypeKind se comportará como si se llamara en el tipo subyacente.

GetTypedefBaseType

El método GetTypedefBaseType devolverá la definición inmediata de la definición typedef. En los ejemplos descritos en la documentación:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

este método devolverá MYSTRUCT * para PMYSTRUCT y PMYSTRUCT para PTRMYSTRUCT.

GetTypedefFinalBaseType

El método GetTypedefFinalBaseType devolverá el tipo final para el que la definición de tipo es una definición. Si typedef es una definición de otra definición de typedef, seguirá seguido la cadena de definición hasta que llegue a un tipo que no sea una definición de tipo y ese tipo se devolverá. En los ejemplos descritos en la documentación:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

este método devolverá MYSTRUCT * cuando se llame a en PMYSTRUCT o PTRMYSTRUCT.

Métodos de creación de tipos 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;

Valores de símbolos constantes: IDebugHostConstant

En el caso de las ubicaciones en las que los valores constantes están presentes en información simbólica (donde un valor determinado es un símbolo que puede o no ser un valor constante), la interfaz IDebugHostConstant expresa la noción de dicha constante. Esto se usa normalmente en lugares como argumentos de plantilla en los que un argumento determinado suele ser un tipo, pero en su lugar puede ser un argumento de plantilla que no sea de tipo (por ejemplo, una constante).

La interfaz IDebugHostConstant se define de la siguiente manera (omitiendo los métodos genéricos implementados por IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostConstant, IDebugHostSymbol)
{
    STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}

GetValue

El método GetValue devuelve el valor de la constante empaquetada en un VARIANT. Es importante tener en cuenta que el método GetType en IDebugHostSymbol puede devolver un símbolo de tipo específico para la constante. En tales casos, no hay ninguna garantía de que el empaquetado del valor constante definido por el símbolo de tipo sea el mismo que el empaquetado devuelto por el método GetValue aquí.

Acceso a miembros de datos: IDebugHostField

La clase IDebugHostField representa un símbolo que es un miembro de datos de una clase, estructura, unión u otra construcción de tipo. No representa datos gratuitos (por ejemplo, datos globales). La interfaz se define de la siguiente manera (omitiendo los métodos genéricos a 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

El método GetLocationKind devuelve el tipo de ubicación en la que se encuentra el símbolo según la enumeración LocationKind. Esta enumeración puede ser uno de los siguientes valores:

Enumerant Significado
LocationMember El campo es un miembro de datos normal de una clase, estructura, unión u otra construcción de tipo. Tiene un desplazamiento que es relativo a la dirección base de la construcción de tipo contenedor. Esta dirección base se representa normalmente mediante el puntero this. El desplazamiento del campo se puede recuperar a través del método GetOffset. Los métodos GetLocation y GetValue producirán un error en un campo que sea LocationMember.
LocationStatic El campo es estático y tiene su propia dirección. El método GetLocation devolverá la ubicación abstracta (por ejemplo: dirección) del campo estático. Los métodos GetOffset y GetValue producirán un error en un campo que sea LocationStatic.
LocationConstant El campo es una constante y tiene un valor. El método GetValue devolverá el valor de la constante. Los métodos GetOffset y GetLocation producirán un error en un campo que sea LocationConstant.
LocationNone El campo no tiene ninguna ubicación. Es posible que el compilador lo haya optimizado o puede ser un campo estático que se declara pero nunca se define. Independientemente de cómo llegó a ser este campo, no tiene presencia física ni valor. Solo está en los símbolos. Todos los métodos de adquisición (GetOffset, GetLocation y GetValue) producirán un error en un campo que sea LocationNone.

GetOffset

Para los campos que tienen un desplazamiento (por ejemplo, campos cuyo tipo de ubicación indica LocationMember), el método GetOffset devolverá el desplazamiento de la dirección base del tipo contenedor (el puntero este) a los datos del propio campo. Estos desplazamientos siempre se expresan como valores de 64 bits sin signo. Si el campo especificado no tiene una ubicación que sea un desplazamiento de la dirección base del tipo contenedor, se producirá un error en el método GetOffset.

GetLocation

Para los campos que tienen una dirección independientemente de la instancia de tipo concreta (por ejemplo, los campos cuyo tipo de ubicación indica LocationStatic), el método GetLocation devolverá la ubicación abstracta (dirección) del campo. Si el campo especificado no tiene una ubicación estática, se producirá un error en el método GetLocation.

GetValue

Para los campos que tienen un valor constante definido dentro de la información simbólica (por ejemplo, los campos cuyo tipo de ubicación indica LocationConstant), el método GetValue devolverá el valor constante del campo. Si el campo especificado no tiene un valor constante, se producirá un error en el método GetValue.

Acceso gratuito a datos: IDebugHostData

Los datos de los módulos que no son miembros de otro tipo se representan mediante la interfaz IDebugHostData. Esa interfaz se define de la siguiente manera (ignorando los métodos genéricos de IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostData, IDebugHostSymbol)
{
    STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
    STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
    STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}

Todos estos métodos son semánticamente equivalentes a sus homólogos en IDebugHostField. La única diferencia es que el método GetLocationKind nunca devolverá LocationMember para obtener datos gratuitos.

GetLocationKind

El método GetLocationKind devuelve el tipo de ubicación en la que se encuentra el símbolo según la enumeración LocationKind. La descripción de esta enumeración se puede encontrar en la documentación de IDebugHostField.

GetLocation

Para los datos que tienen una dirección, el método GetLocation devolverá la ubicación abstracta (dirección) del campo. Si los datos especificados no tienen una ubicación estática, se producirá un error en el método GetLocation.

GetValue

Para los datos que tienen un valor constante definido dentro de la información simbólica (por ejemplo, datos cuyo tipo de ubicación indica LocationConstant), el método GetValue devolverá el valor constante del campo. Si los datos especificados no tienen un valor constante, se producirá un error en el método GetValue.

Clases base: IDebugHostBaseClass

La jerarquía de herencia de un tipo determinado se expresa a través de elementos secundarios de un símbolo de tipo. Si un tipo determinado deriva (herencia) de uno o varios tipos, habrá uno o varios elementos secundarios SymbolBaseClass del símbolo de tipo para el tipo. Cada uno de esos símbolos SymbolBaseClass representa la herencia inmediata de un tipo determinado. El nombre de la clase base es el nombre del símbolo SymbolBaseClass, así como el del símbolo de tipo para la clase base. El método GetType del símbolo SymbolBaseClass se puede usar para obtener el símbolo de tipo para la propia clase base. La jerarquía de herencia completa se puede recorrer explorando de forma recursiva símbolos secundarios SymbolBaseClass. Cada uno de estos símbolos de clase base se expresa mediante la interfaz IDebugHostBaseClass que se define de la siguiente manera (ignorando los métodos genéricos de IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostBaseClass, IDebugHostSymbol)
{
    STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
}

GetOffset

El método GetOffset devuelve el desplazamiento de la clase base desde la dirección base de la clase derivada. Este desplazamiento puede ser cero o puede ser un valor positivo sin signo de 64 bits.

Símbolos públicos: IDebugHostPublic

Los símbolos públicos representan elementos de la tabla pública dentro de un archivo de símbolos. Son, en efecto, direcciones de exportación. No hay información de tipo asociada a un símbolo público: solo una dirección. A menos que el autor de la llamada solicite explícitamente un símbolo público, el host de depuración prefiere devolver símbolos privados para cada consulta. Un símbolo público se expresa mediante la interfaz IDebugHostPublic que se define de la siguiente manera (omitir los métodos genéricos de IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostPublic, IDebugHostSymbol)
{
    STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
    STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
}

Todos estos métodos son semánticamente equivalentes a sus homólogos en IDebugHostField. La única diferencia es que el método GetLocationKind nunca devolverá LocationMember o LocationConstant para dichos símbolos.

GetLocationKind

El método GetLocationKind devuelve el tipo de ubicación en la que se encuentra el símbolo según la enumeración LocationKind. La descripción de esta enumeración se puede encontrar en la documentación de IDebugHostField.

GetLocation

Para los datos que tienen una dirección, el método GetLocation devolverá la ubicación abstracta (dirección) del campo. Si el público especificado no tiene una ubicación estática, se producirá un error en el método GetLocation.

Firmas de módulo y coincidencia de versiones: IDebugHostModuleSignature

Las firmas de módulo representan un medio para comprobar si un módulo determinado cumple un conjunto de criterios relacionados con la nomenclatura y el control de versiones. Se crea una firma de módulo mediante el método CreateModuleSignature en IDebugHostSymbols. Puede coincidir con el nombre del módulo y un intervalo opcional de números de versión para el módulo. Una vez creada dicha firma, el cliente recibe una interfaz IDebugHostModuleSignature que se define de la siguiente manera:

DECLARE_INTERFACE_(IDebugHostModuleSignature, IUnknown)
{
    STDMETHOD(IsMatch)(_In_ IDebugHostModule* pModule, _Out_ bool* isMatch) PURE;
}

IsMatch

El método IsMatch compara un módulo determinado (dado por un símbolo IDebugHostModule) con una firma, comparando el nombre y la versión del módulo con el nombre y el intervalo de versiones indicados en la firma. Indicación de si el símbolo del módulo especificado coincide con la firma.

Firmas de tipo y coincidencia de tipos: IDebugHostTypeSignature

Las firmas de tipo representan un medio para comprobar si una instancia de tipo determinada cumple un conjunto de criterios sobre el nombre del tipo, los argumentos genéricos para el tipo y el módulo en el que se encuentra el tipo. Se crea una firma de tipo a través del método CreateTypeSignature en IDebugHostSymbols. Una vez creada dicha firma, el cliente recibe una interfaz IDebugHostTypeSignature que se define de la siguiente manera:

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

El método GetHashCode devuelve un código hash de 32 bits para la firma de tipo. El host de depuración garantiza que hay sincronización en la implementación entre el código hash devuelto para las instancias de tipo y el código hash devuelto para las firmas de tipo. Con la excepción de una coincidencia global, si una instancia de tipo es capaz de hacer coincidir una firma de tipo, ambos tendrán el mismo código hash de 32 bits. Esto permite una comparación rápida inicial y una coincidencia entre una instancia de tipo y una gran cantidad de firmas de tipo registradas con el administrador de modelos de datos.

IsMatch

El método IsMatch devuelve una indicación de si una instancia de tipo determinada coincide con los criterios especificados en la firma de tipo. Si lo hace, se devuelve una indicación de esto, así como un enumerador que indicará todas las partes específicas de la instancia de tipo (como símbolos) que coinciden con caracteres comodín en la firma de tipo.

CompareAgainst

El método CompareAgainst compara la firma de tipo con otra firma de tipo y devuelve cómo se comparan las dos firmas. El resultado de la comparación que se devuelve es un miembro de la enumeración SignatureComparison, que se define de la siguiente manera:

Enumerant Significado
Unrelated No hay ninguna relación entre las dos firmas o tipos que se comparan.
Ambigua Una firma o tipo se compara ambiguamente con la otra. En el caso de dos firmas de tipo, esto significa que hay instancias de tipo potenciales que podrían coincidir con cualquier firma igual de bien. Por ejemplo, las dos firmas de tipo que se muestran a continuación son ambiguas. Firma 1: std::pair<*, int> Firma 2: std::pair<int,*> porque la instancia std::pair<int, int> de tipo coincide con una igual de bien (ambas tienen una coincidencia concreta y una de caracteres comodín).
LessSpecific Una firma o tipo es menos específica que la otra. A menudo, esto significa que la firma menos específica tiene un carácter comodín donde el más específico tiene un tipo concreto. Por ejemplo, la primera firma siguiente es menos específica que la segunda. Firma 1: std::pair<*, int> Firma 2: std::pair<int, int> porque tiene un carácter comodín (el *) donde el segundo tiene un tipo concreto (int).
MoreSpecific Una firma o tipo es más específica que la otra. A menudo, esto significa que la firma más específica tiene un tipo concreto donde el menos específico tiene un carácter comodín. Por ejemplo, la primera firma siguiente es más específica que la segunda. Firma 1: std::pair<int, int> Firma 2: std::pair<*, int> porque tiene un tipo concreto (int) donde el segundo tiene un carácter comodín ().*
Idéntico Las dos firmas o tipos son idénticas.

Vea también

Este tema forma parte de una serie que describe las interfaces accesibles desde C++, cómo usarlas para crear una extensión de depurador basada en C++ y cómo usar otras construcciones de modelo de datos (por ejemplo: JavaScript o NatVis) desde una extensión de modelo de datos de C++.

Información general sobre el modelo de datos del depurador de C++

Interfaces de C++ del modelo de datos del depurador

Objetos C++ del modelo de datos del depurador

Interfaces adicionales del modelo de datos del depurador de C++

Conceptos de C++ del modelo de datos del depurador

Scripting del modelo de datos del depurador de C++