Objets C++ du modèle de données du débogueur

Cette rubrique explique comment utiliser les objets C++ du modèle de données du débogueur et comment ils peuvent étendre les fonctionnalités du débogueur.

Modèle objet du débogueur principal

L’une des choses les plus fondamentales et les plus puissantes du modèle de données est qu’il normalise la définition de ce qu’est un objet et la façon dont on interagit avec un objet. L’interface IModelObject encapsule la notion d’un objet, qu’il s’agisse d’un entier, d’une valeur à virgule flottante, d’une chaîne, d’un type complexe dans l’espace d’adressage cible du débogueur ou d’un concept de débogueur comme la notion d’un processus ou d’un module.

Il existe plusieurs éléments différents qui peuvent être conservés dans (ou placés dans) un IModelObject :

  • Valeurs intrinsèques : un IModelObject peut être un conteneur pour un certain nombre de types de base : 8, 16, 32 ou 64 bits, entiers signés ou non signés, booléens, chaînes, erreurs ou la notion de vide.

  • Objets natifs : un IModelObject peut représenter un type complexe (tel que défini par le système de type du débogueur) dans l’espace d’adressage de tout ce que le débogueur cible

  • Objets synthétiques : un IModelObject peut être un objet dynamique : une collection de tuples clé/valeur/métadonnées et un ensemble de concepts qui définissent des comportements qui ne sont pas simplement représentés par des paires clé/valeur.

  • Propriétés : un IModelObject peut représenter une propriété : quelque chose dont la valeur peut être récupérée ou modifiée avec un appel de méthode. Une propriété dans un IModelObject est en fait une interface IModelPropertyAccessor boxée dans un IModelObject

  • Méthodes : un IModelObject peut représenter une méthode : quelque chose que vous pouvez appeler avec un ensemble d’arguments et obtenir une valeur de retour. Une méthode au sein d’un IModelObject est en fait une interface IModelMethod boxée dans un IModelObject

Extensibilité dans le modèle objet

Un IModelObject n’est pas un objet isolé. En plus de représenter l’un des types d’objets indiqués ci-dessus, chaque objet a la notion d’une chaîne de modèles de données parents. Cette chaîne se comporte comme une chaîne de prototype JavaScript. Au lieu d’une chaîne linéaire de prototypes comme JavaScript, chaque objet de modèle de données définit une chaîne linéaire de modèles parents. Chacun de ces modèles parents à son tour a une autre chaîne linéaire de son propre ensemble de parents. En substance, chaque objet est une agrégation des fonctionnalités (propriétés, etc.) de lui-même et de chaque objet de cette arborescence. Lorsqu’une propriété spécifique est interrogée, si l’objet sur lequel elle est interrogée ne prend pas en charge cette propriété, la requête est passée dans l’ordre linéaire à chaque parent à son tour. Cela crée un comportement où la recherche d’une propriété est résolue par une recherche en profondeur d’abord dans l’arborescence d’agrégation.

L’extensibilité au sein de ce modèle objet est très simple étant donné cette notion que chaque objet est un agrégat de lui-même et l’arborescence des modèles parents. Une extension peut entrer et s’ajouter à la liste des modèles parent pour un autre objet. Cette opération étend l’objet. De cette manière, il est possible d’ajouter des fonctionnalités à n’importe quoi : une instance particulière d’un objet ou d’une valeur, un type natif, le concept du débogueur de ce qu’est un processus ou un thread, ou même la notion de « tous les objets itérables ».

Contexte, contexte et contexte : ce pointeur, l’espace d’adressage et les données privées d’implémentation

Il existe trois notions de contexte qui sont nécessaires pour comprendre dans le contexte du modèle objet.

Contexte : pointeur de ce type

Étant donné qu’une propriété ou une méthode donnée peut être implémentée à n’importe quel niveau de l’arborescence du modèle de données, il est nécessaire que l’implémentation de la méthode ou de la propriété puisse accéder à l’objet d’origine (ce que vous pouvez appeler le pointeur en C++ ou cet objet en JavaScript. Cet objet instance est passé à diverses méthodes en tant que premier argument appelé contexte dans les méthodes décrites.

Contexte : espace d’adressage

Il est important de noter que contrairement aux modèles d’extension précédents où le contexte (la cible, le processus, le thread que vous examinez) est un concept d’interface utilisateur avec toutes les API par rapport à l’état actuel de l’interface utilisateur, les interfaces de modèle de données prennent généralement ce contexte explicitement ou implicitement comme une interface IDebugHostContext . Chaque IModelObject dans le modèle de données contient ce type d’informations de contexte et peut propager ce contexte aux objets qu’il retourne. Cela signifie que lorsque vous lisez une valeur native ou une valeur de clé à partir d’un IModelObject, il lit la cible et traite l’emplacement d’où l’objet a été acquis à l’origine.

Il existe une valeur constante explicite, USE_CURRENT_HOST_CONTEXT, qui peut être passée aux méthodes qui prennent un argument IDebugHostContext . Cette valeur indique que le contexte doit effectivement être l’état actuel de l’interface utilisateur du débogueur. Toutefois, cette notion doit être explicite.

Contexte : Données privées d’implémentation

N’oubliez pas que chaque objet du modèle de données est en fait un agrégat de l’objet instance et de l’arborescence des modèles parents qui sont attachés. Chacun de ces modèles parents (qui peut être lié dans les chaînes de nombreux objets différents) peut associer des données d’implémentation privées à n’importe quel objet instance. Chaque IModelObject créé conceptuellement a une table de hachage qui mappe d’un modèle parent particulier à des données instance privées définies par une interface IUnknown. Cela permet à un modèle parent de mettre en cache des informations sur chaque instance ou d’avoir des données arbitraires associées.

Ce type de contexte est accessible via les méthodes GetContextForDataModel et SetContextForDataModel sur IModelObject.

Interface d’objet du débogueur principal : IModelObject


L’interface IModelObject est définie comme suit :

DECLARE_INTERFACE_(IModelObject, IUnknown)
{
    STDMETHOD(QueryInterface)(_In_ REFIID iid, _COM_Outptr_ PVOID* iface);
    STDMETHOD_(ULONG, AddRef)();
    STDMETHOD_(ULONG, Release)() PURE;
    STDMETHOD(GetContext)(_COM_Outptr_result_maybenull_ IDebugHostContext** context) PURE;
    STDMETHOD(GetKind)(_Out_ ModelObjectKind *kind) PURE;
    STDMETHOD(GetIntrinsicValue)(_Out_ VARIANT* intrinsicData);
    STDMETHOD(GetIntrinsicValueAs)(_In_ VARTYPE vt, _Out_ VARIANT* intrinsicData) PURE;
    STDMETHOD(GetKeyValue)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(SetKeyValue)(_In_ PCWSTR key, _In_opt_ IModelObject* object) PURE;
    STDMETHOD(EnumerateKeyValues)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
    STDMETHOD(GetRawValue)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(EnumerateRawValues)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;
    STDMETHOD(Dereference)(_COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(TryCastToRuntimeType)(_COM_Errorptr_ IModelObject** runtimeTypedObject) PURE;
    STDMETHOD(GetConcept)(_In_ REFIID conceptId, _COM_Outptr_ IUnknown** conceptInterface, _COM_Outptr_opt_result_maybenull_ IKeyStore** conceptMetadata) PURE;
    STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
    STDMETHOD(GetTypeInfo)(_Out_ IDebugHostType** type) PURE;
    STDMETHOD(GetTargetInfo)(_Out_ Location* location, _Out_ IDebugHostType** type) PURE;
    STDMETHOD(GetNumberOfParentModels)(_Out_ ULONG64* numModels) PURE;
    STDMETHOD(GetParentModel)(_In_ ULONG64 i, _COM_Outptr_ IModelObject **model, _COM_Outptr_result_maybenull_ IModelObject **contextObject) PURE;
    STDMETHOD(AddParentModel)(_In_ IModelObject* model, _In_opt_ IModelObject* contextObject, _In_ bool override) PURE;
    STDMETHOD(RemoveParentModel)(_In_ IModelObject* model) PURE;
    STDMETHOD(GetKey)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(GetKeyReference)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** objectReference, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(SetKey)(_In_ PCWSTR key, _In_opt_ IModelObject* object, _In_opt_ IKeyStore* metadata) PURE;
    STDMETHOD(ClearKeys)() PURE;
    STDMETHOD(EnumerateKeys)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
    STDMETHOD(EnumerateKeyReferences)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
    STDMETHOD(SetConcept)(_In_ REFIID conceptId, _In_ IUnknown* conceptInterface, _In_opt_ IKeyStore* conceptMetadata) PURE;
    STDMETHOD(ClearConcepts)() PURE;
    STDMETHOD(GetRawReference)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(EnumerateRawReferences)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;
    STDMETHOD(SetContextForDataModel)(_In_ IModelObject* dataModelObject, _In_ IUnknown* context) PURE;
    STDMETHOD(GetContextForDataModel)(_In_ IModelObject* dataModelObject, _Out_ IUnknown** context) PURE;
    STDMETHOD(Compare)(_In_ IModelObject* other, _COM_Outptr_opt_result_maybenull_ IModelObject **ppResult) PURE;
    STDMETHOD(IsEqualTo)(_In_ IModelObject* other, _Out_ bool* equal) PURE;
}

Méthodes de base

Voici des méthodes générales applicables à tout type d’objet représenté par un IModelObject.

STDMETHOD(GetKind)(_Out_ ModelObjectKind *kind) PURE;
STDMETHOD(GetContext)(_COM_Outptr_result_maybenull_ IDebugHostContext** context) PURE;
STDMETHOD(GetIntrinsicValue)(_Out_ VARIANT* intrinsicData);
STDMETHOD(GetIntrinsicValueAs)(_In_ VARTYPE vt, _Out_ VARIANT* intrinsicData) PURE;
STDMETHOD(Compare)(_In_ IModelObject* other, _COM_Outptr_opt_result_maybenull_ IModelObject **ppResult) PURE;
STDMETHOD(IsEqualTo)(_In_ IModelObject* other, _Out_ bool* equal) PURE;
STDMETHOD(Dereference)(_COM_Errorptr_ IModelObject** object) PURE;

GetKind

La méthode GetKind retourne le type d’objet qui est boxé à l’intérieur de l’IModelObject.

GetContext

La méthode GetContext retourne le contexte hôte associé à l’objet.

GetIntrinsicValue

La méthode GetIntrinsicValue retourne la chose qui est boxée à l’intérieur d’un IModelObject. Cette méthode ne peut être appelée légalement que sur les interfaces IModelObject qui représentent une intrinsèque boxée ou une interface particulière qui est boxée. Il ne peut pas être appelé sur les objets natifs, les objets sans valeur, les objets synthétiques et les objets de référence. La méthode GetIntrinsicValueAs se comporte comme la méthode GetIntrinsicValue, sauf qu’elle convertit la valeur en type variant spécifié. Si la conversion ne peut pas être effectuée, la méthode retourne une erreur.

IsEqualTo

La méthode IsEqualTo compare deux objets de modèle et retourne s’ils sont égaux en valeur. Pour les objets qui ont un ordre, cette méthode renvoyant true équivaut à la méthode Compare qui retourne 0. Pour les objets qui n’ont pas de classement, mais qui sont comparables, la méthode Compare échoue, mais ce n’est pas le cas. La signification d’une comparaison basée sur des valeurs est définie par le type d’objet. À l’heure actuelle, cela est défini uniquement pour les types intrinsèques et les objets d’erreur. Il n’existe aucun concept actuel de modèle de données pour l’équatabilité.

Dereference

La méthode Dereference déréférence un objet. Cette méthode peut être utilisée pour déréférencer une référence basée sur un modèle de données (ObjectTargetObjectReference, ObjectKeyReference) ou une référence de langage natif (pointeur ou référence de langage). Il est important de noter que cette méthode supprime un seul niveau de sémantique de référence sur l’objet. Il est tout à fait possible, pour instance, d’avoir une référence de modèle de données à une référence de langage. Dans ce cas, l’appel de la méthode Dereference la première fois supprime la référence du modèle de données et laisse la référence de langue. L’appel de déréférencement sur cet objet résultant supprime par la suite la référence de langue et retourne la valeur native sous cette référence.

Méthodes de manipulation de clé

Tout objet synthétique qui est un dictionnaire de tuples de clés, de valeurs et de métadonnées possède une série de méthodes pour manipuler ces clés, valeurs et métadonnées qui leur sont associées.

Les formes basées sur les valeurs des API sont les suivantes :

STDMETHOD(GetKeyValue)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(SetKeyValue)(_In_ PCWSTR key, _In_opt_ IModelObject* object) PURE;
STDMETHOD(EnumerateKeyValues)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
The key based forms of the APIs (including those used for key creation) are: 
STDMETHOD(GetKey)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(SetKey)(_In_ PCWSTR key, _In_opt_ IModelObject* object, _In_opt_ IKeyStore* metadata) PURE;
STDMETHOD(EnumerateKeys)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
STDMETHOD(ClearKeys)() PURE;

Les formes basées sur des références des API sont les suivantes :

STDMETHOD(GetKeyReference)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** objectReference, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(EnumerateKeyReferences)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;

GetKeyValue

La méthode GetKeyValue est la première méthode vers laquelle un client se tournera pour obtenir la valeur (et les métadonnées associées) d’une clé donnée par nom. Si la clé est un accesseur de propriété, c’est-à-dire sa valeur en tant qu’IModelObject qui est un IModelPropertyAccessor en boîte, la méthode GetKeyValue appelle automatiquement la méthode GetValue de l’accesseur de propriété afin de récupérer la valeur réelle.

SetKeyValue

La méthode SetKeyValue est la première méthode vers laquelle un client doit se tourner pour définir la valeur d’une clé. Cette méthode ne peut pas être utilisée pour créer une clé sur un objet. Il définit uniquement la valeur d’une clé existante. Notez que de nombreuses clés sont en lecture seule (par exemple, elles sont implémentées par un accesseur de propriété qui retourne E_NOT_IMPL à partir de sa méthode SetValue). Cette méthode échoue lorsqu’elle est appelée sur une clé en lecture seule.

EnumerateKeyValues

La méthode EnumerateKeyValues est la première méthode vers laquelle un client doit se tourner pour énumérer toutes les clés d’un objet (cela inclut toutes les clés implémentées n’importe où dans l’arborescence des modèles parents). Il est important de noter que EnumerateKeyValues énumère toutes les clés définies par des noms en double dans l’arborescence des objets ; toutefois , les méthodes telles que GetKeyValue et SetKeyValue ne manipulent que la première instance d’une clé portant le nom donné, comme découvert par la traversée en profondeur.

GetKey

La méthode GetKey obtient la valeur de (et les métadonnées associées à) une clé donnée par nom. La plupart des clients doivent utiliser la méthode GetKeyValue à la place. Si la clé est un accesseur de propriété, l’appel de cette méthode renvoie l’accesseur de propriété (une interface IModelPropertyAccessor) boxé dans un IModelObject. Contrairement à GetKeyValue, cette méthode ne résout pas automatiquement la valeur sous-jacente de la clé en appelant la méthode GetValue. Cette responsabilité est celle de l’appelant.

SetKey

La méthode SetKey est la méthode vers laquelle un client doit se tourner pour créer une clé sur un objet (et éventuellement associer des métadonnées à la clé créée). Si un objet donné a déjà une clé avec le nom donné, l’un des deux comportements se produit. Si la clé se trouve sur le instance donné par ceci, la valeur de cette clé est remplacée comme si la clé d’origine n’existait pas. Si, en revanche, la clé se trouve dans la chaîne des modèles de données parents de l’instance donné par ce, une nouvelle clé avec le nom donné est créée sur le instance donné par ce. En effet, l’objet aurait deux clés du même nom (de la même façon qu’une classe dérivée ombrage d’un membre du même nom qu’une classe de base).

EnumerateKeys

La méthode EnumerateKeys se comporte comme la méthode EnumerateKeyValues, sauf qu’elle ne résout pas automatiquement les accesseurs de propriété sur l’objet . Cela signifie que si la valeur d’une clé est un accesseur de propriété, la méthode EnumerateKeys retourne l’accesseur de propriété (un IModelPropertyAccessorInterface) boxé dans un IModelObject au lieu d’appeler automatiquement la méthode GetValue. Cela est similaire à la différence entre GetKey et GetKeyValue.

ClearKeys

La méthode ClearKeys supprime toutes les clés, ainsi que leurs valeurs et métadonnées associées, de la instance de l’objet spécifié par ce. Cette méthode n’a aucun effet sur les modèles parents attachés à l’objet particulier instance.

GetKeyReference

La méthode GetKeyReference recherche une clé du nom donné sur l’objet (ou sa chaîne de modèle parente) et retourne une référence à cette clé donnée par une interface IModelKeyReference boxée dans un IModelObject. Cette référence peut ensuite être utilisée pour obtenir ou définir la valeur de la clé.

EnumerateKeyReferences

La méthode EnumerateKeyReferences se comporte comme la méthode EnumerateKeyValues, sauf qu’elle retourne des références aux clés qu’elle énumère (données par une interface IModelKeyReference boxée dans un IModelObject) au lieu de la valeur de la clé. Ces références peuvent être utilisées pour obtenir ou définir la valeur sous-jacente des clés.

Méthodes de manipulation de concept

Outre qu’un objet de modèle est un dictionnaire de tuples clé/valeur/métadonnées, il s’agit également d’un conteneur de concepts. Un concept est quelque chose d’abstrait qui peut être effectué sur ou par un objet . Les concepts sont, par essence, un magasin dynamique d’interfaces qu’un objet prend en charge. Un certain nombre de concepts sont définis aujourd’hui par le modèle de données :

Concept Interface Description
IDataModelConcept Le concept est un modèle parent. Si ce modèle est automatiquement attaché à un type natif via une signature de type inscrite, la méthode InitializeObject est automatiquement appelée chaque fois qu’un nouvel objet de ce type est instancié.
IStringDisplayableConcept L’objet peut être converti en chaîne à des fins d’affichage.
IIterableConcept L’objet est un conteneur et peut être itéré.
IIndexableConcept L’objet est un conteneur et peut être indexé (accessible via un accès aléatoire) dans une ou plusieurs dimensions.
IPreferredRuntimeTypeConcept L’objet comprend mieux les types dérivés que le système de type sous-jacent est capable de fournir et souhaite gérer ses propres conversions du type statique au type runtime.
IDynamicKeyProviderConcept L’objet est un fournisseur dynamique de clés et souhaite prendre en charge toutes les requêtes clés du modèle de données de base. Cette interface est généralement utilisée comme pont vers des langages dynamiques tels que JavaScript.
IDynamicConceptProviderConcept L’objet est un fournisseur dynamique de concepts et souhaite prendre en charge toutes les requêtes de concept à partir du modèle de données de base. Cette interface est généralement utilisée comme pont vers des langages dynamiques tels que JavaScript.

Les méthodes suivantes sur IModelObject sont utilisées pour manipuler les concepts pris en charge par un objet.

STDMETHOD(GetConcept)(_In_ REFIID conceptId, _COM_Outptr_ IUnknown** conceptInterface, _COM_Outptr_opt_result_maybenull_ IKeyStore** conceptMetadata) PURE;
STDMETHOD(SetConcept)(_In_ REFIID conceptId, _In_ IUnknown* conceptInterface, _In_opt_ IKeyStore* conceptMetadata) PURE;
STDMETHOD(ClearConcepts)() PURE;

GetConcept

La méthode GetConcept recherche un concept sur l’objet (ou sa chaîne de modèle parente) et retourne un pointeur d’interface vers l’interface de concept. Le comportement et les méthodes d’une interface de concept sont spécifiques à chaque concept. Il est important de noter, toutefois, que la plupart des interfaces de concept exigent que l’appelant passe explicitement l’objet de contexte (ou ce que l’on pourrait traditionnellement appeler le pointeur this). Il est important de s’assurer que l’objet de contexte correct est passé à chaque interface de concept.

SetConcept

La méthode SetConcept place un concept spécifié sur l’objet instance spécifié par le pointeur this. Si un modèle parent attaché à l’objet instance spécifié par cela prend également en charge le concept, l’implémentation dans le instance remplace celle dans le modèle parent.

ClearConcepts

La méthode ClearConcepts supprime tous les concepts de la instance de l’objet spécifié par ce.

Méthodes d’objet natives

Alors que de nombreux objets de modèle font référence à des caractéristiques intrinsèques (par exemple, des entiers, des chaînes) ou des constructions synthétiques (dictionnaire de tuples et de concepts de clé/valeur/métadonnées), un objet de modèle peut également faire référence à une construction native (par exemple, un type défini par l’utilisateur dans l’espace d’adressage de la cible de débogage). L’interface IModelObject contient une série de méthodes qui accèdent à des informations sur ces objets natifs. Ces méthodes sont les suivantes :

STDMETHOD(GetRawValue)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(EnumerateRawValues)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;
STDMETHOD(TryCastToRuntimeType)(_COM_Errorptr_ IModelObject** runtimeTypedObject) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetTypeInfo)(_Out_ IDebugHostType** type) PURE;
STDMETHOD(GetTargetInfo)(_Out_ Location* location, _Out_ IDebugHostType** type) PURE;
STDMETHOD(GetRawReference)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(EnumerateRawReferences)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;

GetRawValue

La méthode GetRawValue recherche une construction native dans l’objet donné. Une telle construction peut être un champ, une classe de base, un champ dans une classe de base, une fonction membre, etc.

EnumerateRawValues

La méthode EnumerateRawValues énumère tous les enfants natifs (par exemple : champs, classes de base, etc...)de l’objet donné.

TryCastToRuntimeType

La méthode TryCastToRuntimeType demande à l’hôte de débogage d’effectuer une analyse et de déterminer le type d’exécution réel (par exemple, la classe la plus dérivée) de l’objet donné. L’analyse exacte utilisée est spécifique à l’hôte de débogage et peut inclure RTTI (informations sur le type d’exécution C++), l’examen de la structure V-Table(table de fonction virtuelle) de l’objet ou tout autre moyen que l’hôte peut utiliser pour déterminer de manière fiable le type dynamique/runtime à partir du type statique. L’échec de la conversion en type runtime ne signifie pas que cet appel de méthode échouera. Dans ce cas, la méthode retourne l’objet donné (le pointeur this) dans l’argument de sortie.

GetLocation

La méthode GetLocation retourne l’emplacement de l’objet natif. Bien qu’un tel emplacement soit généralement une adresse virtuelle dans l’espace d’adressage de la cible de débogage, il ne l’est pas nécessairement. L’emplacement retourné par cette méthode est un emplacement abstrait qui peut être une adresse virtuelle, peut indiquer un emplacement dans un registre ou un sous-registre, ou peut indiquer un autre espace d’adressage arbitraire tel que défini par l’hôte de débogage. Si le champ HostDefined de l’objet Location obtenu est 0, il indique que l’emplacement est en fait une adresse virtuelle. Cette adresse virtuelle peut être récupérée en examinant le champ Offset de l’emplacement résultant. Toute valeur différente de zéro du champ HostDefined indique un autre espace d’adressage où le champ Offset est le décalage dans cet espace d’adressage. La signification exacte des valeurs HostDefined non nulles ici est privée pour l’hôte de débogage.

GetTypeInfo

La méthode GetTypeInfo retourne le type natif de l’objet donné. Si l’objet n’a pas d’informations de type natif associées (par exemple : il s’agit d’une intrinsèque, etc...), l’appel réussit toujours, mais retourne null.

GetTargetInfo

La méthode GetTargetInfo est en fait une combinaison des méthodes GetLocation et GetTypeInfo qui retournent à la fois l’emplacement abstrait et le type natif de l’objet donné.

GetRawReference

La méthode GetRawReference recherche une construction native dans l’objet donné et retourne une référence à celui-ci. Une telle construction peut être un champ, une classe de base, un champ dans une classe de base, une fonction membre, etc. Il est important de distinguer la référence retournée ici (un objet de type ObjectTargetObjectReference) d’une référence de langage (par exemple, une référence de style & C++ ou && référence de style).

EnumerateRawReferences

La méthode EnumerateRawReferences énumère les références à tous les enfants natifs (par exemple : champs, classes de base, etc...)de l’objet donné.

Méthodes d’extensibilité

Comme décrit précédemment, un objet de modèle se comporte très similaire à un objet JavaScript et à sa chaîne prototype. Outre les instance représentées par une interface IModelObject donnée, il peut y avoir un nombre arbitraire de modèles parents attachés à l’objet (chacun d’eux pouvant, à son tour, avoir un nombre arbitraire de modèles parents attachés à eux). Il s’agit du principal moyen d’extensibilité dans le modèle de données. Si une propriété ou un concept donné ne peut pas se trouver dans un instance donné, une recherche de profondeur d’abord dans l’arborescence d’objets (définie par les modèles parents) enracinée au instance est effectuée.

Les méthodes suivantes manipulent la chaîne de modèles parents associés à un IModelObject donné instance :

STDMETHOD(GetNumberOfParentModels)(_Out_ ULONG64* numModels) PURE;
STDMETHOD(GetParentModel)(_In_ ULONG64 i, _COM_Outptr_ IModelObject **model, _COM_Outptr_result_maybenull_ IModelObject **contextObject) PURE;
STDMETHOD(AddParentModel)(_In_ IModelObject* model, _In_opt_ IModelObject* contextObject, _In_ bool override) PURE;
STDMETHOD(RemoveParentModel)(_In_ IModelObject* model) PURE;
STDMETHOD(SetContextForDataModel)(_In_ IModelObject* dataModelObject, _In_ IUnknown* context) PURE;
STDMETHOD(GetContextForDataModel)(_In_ IModelObject* dataModelObject, _Out_ IUnknown** context) PURE;

GetNumberOfParentModels

La méthode GetNumberOfParentModels retourne le nombre de modèles parents attachés à l’objet donné instance. Les modèles parents sont recherchés pour les propriétés en profondeur d’abord dans l’ordre linéaire de la chaîne de modèle parent.

GetParentModel

La méthode GetParentModel retourne le i-ième modèle parent dans la chaîne de modèle parent de l’objet donné. Les modèles parents sont recherchés pour une propriété ou un concept dans l’ordre linéaire dans lequel ils sont ajoutés ou énumérés. Le modèle parent avec l’index i de zéro est recherché (hiérarchiquement) avant le modèle parent avec l’index i + 1.

AddParentModel

La méthode AddParentModel ajoute un nouveau modèle parent à l’objet donné. Un tel modèle peut être ajouté à la fin de la chaîne de recherche (l’argument de remplacement est spécifié comme false) ou au début de la chaîne de recherche (l’argument de remplacement est spécifié comme true). En outre, chaque modèle parent peut éventuellement ajuster le contexte (le pointeur sémantique ce) pour n’importe quelle propriété ou concept sur le parent donné (ou toute personne dans sa hiérarchie parente). L’ajustement du contexte est rarement utilisé, mais autorise certains concepts puissants tels que l’incorporation d’objets, la construction d’espaces de noms, etc.

RemoveParentModel

RemoveParentModel supprime un modèle parent spécifié de la chaîne de recherche parente de l’objet donné.

SetContextForDataModel

La méthode SetContextForDataModel est utilisée par l’implémentation d’un modèle de données pour placer des données d’implémentation sur instance objets. Sur le plan conceptuel, chaque IModelObject (appelez ceci le instance par souci de simplicité) contient une table de hachage d’état. La table de hachage est indexée par un autre IModelObject (appelez cela le modèle de données pour plus de simplicité) qui se trouve dans la hiérarchie du modèle parent de l’instance. La valeur contenue dans ce hachage est un ensemble d’informations d’état comptabilisées de référence représentées par un instance IUnknown. Une fois que le modèle de données définit cet état sur le instance il peut stocker des données d’implémentation arbitraires qui peuvent être récupérées pendant des opérations telles que les getters de propriétés.

GetContextForDataModel

La méthode GetContextForDataModel est utilisée pour récupérer des informations de contexte qui ont été configurées avec un appel antérieur à SetContextForDataModel. Cette opération récupère les informations d’état qui ont été définies sur un objet instance par un modèle de données plus haut dans la hiérarchie du modèle parent de l’objet instance. Pour plus d’informations sur ce contexte/état et sa signification, consultez la documentation relative à SetContextForDataModel.

Types d’objets principaux du modèle de données du débogueur

Un objet dans le modèle de données est similaire à la notion d’objet dans .NET. Il s’agit du conteneur générique dans lequel la construction que le modèle de données comprend peut être boxée. Outre les objets natifs et les objets synthétiques (dynamiques), il existe une série de types d’objets principaux qui peuvent être placés (ou placés en boîte) dans le conteneur d’un IModelObject. Le conteneur dans lequel la plupart de ces valeurs sont placées est un VARIANT COM/OLE standard avec un certain nombre de restrictions supplémentaires imposées à ce que ce VARIANT peut contenir. Les types les plus basiques sont les suivants :

  • Valeurs 8 bits non signées et signées (VT_UI1, VT_I1)
  • Valeurs 16 bits non signées et signées (VT_UI2, VT_UI2)
  • Valeurs 32 bits non signées et signées (VT_UI4, VT_I4)
  • Valeurs 64 bits non signées et signées (VT_UI8, VT_I8)
  • Valeurs à virgule flottante simple et double précision (VT_R4, VT_R8)
  • Chaînes (VT_BSTR)
  • Booleans (VT_BOOL)

En plus de ces types de base, un certain nombre d’objets de modèle de données principaux sont placés dans IModelObject défini par VT_UNKNOWN où l’IUnknown stocké est garanti pour implémenter une interface spécifique. Ces types sont les suivants :

  • Accesseurs de propriété (IModelPropertyAccessor)
  • Objets de méthode (IModelMethod)
  • Objets de référence clés (IModelKeyReference ou IModelKeyReference2)
  • Objets de contexte (IDebugModelHostContext)

Accesseurs de propriété : IModelPropertyAccessor

Un accesseur de propriété dans le modèle de données est une implémentation de l’interface IModelPropertyAccessor qui est boxée dans un IModelObject. L’objet de modèle retourne une sorte d’ObjectPropertyAccessor lorsqu’il est interrogé et que la valeur intrinsèque est une VT_UNKNOWN qui est garantie pour être interrogeable pour IModelPropertyAccessor. En cours de traitement, il est garanti qu’il est statiquement castable en IModelPropertyAccessor.

Un accesseur de propriété est un moyen indirect d’obtenir un appel de méthode pour obtenir et définir une valeur de clé dans le modèle de données. Si la valeur d’une clé donnée est un accesseur de propriété, les méthodes GetKeyValue et SetKeyValue le remarquent automatiquement et appellent les méthodes GetValue ou SetValue sous-jacentes de l’accesseur de propriété, le cas échéant.

L’interface IModelPropertyAccessor est définie comme suit :

DECLARE_INTERFACE_(IModelPropertyAccessor, IUnknown)
{
    STDMETHOD(GetValue)(_In_ PCWSTR key, _In_opt_ IModelObject* contextObject, _COM_Outptr_ IModelObject** value) PURE;
    STDMETHOD(SetValue)(_In_ PCWSTR key, _In_opt_ IModelObject* contextObject, _In_ IModelObject* value) PURE; 
}

GetValue

La méthode GetValue est le getter de l’accesseur de propriété. Il est appelé chaque fois qu’un client souhaite extraire la valeur sous-jacente de la propriété. Notez que tout appelant qui obtient directement un accesseur de propriété est responsable de la transmission du nom de clé et de l’objet de instance précis (ce pointeur) à la méthode GetValue de l’accesseur de propriété.

SetValue

La méthode SetValue est le setter de l’accesseur de propriété. Il est appelé chaque fois qu’un client souhaite affecter une valeur à la propriété sous-jacente. De nombreuses propriétés sont en lecture seule. Dans ce cas, l’appel de la méthode SetValue retourne E_NOTIMPL. Notez que tout appelant qui obtient directement un accesseur de propriété est responsable de la transmission du nom de clé et de l’objet instance précis (ce pointeur) à la méthode SetValue de l’accesseur de propriété.

Méthodes : IModelMethod

Une méthode dans le modèle de données est une implémentation de l’interface IModelMethod qui est boxée dans un IModelObject. L’objet de modèle retourne une sorte d’ObjetMethod lorsqu’il est interrogé et que la valeur intrinsèque est une VT_UNKNOWN qui est garantie pour être interrogeable pour IModelMethod. En cours de traitement, il est garanti d’être statiquement castable en IModelMethod. Toutes les méthodes du modèle de données sont de nature dynamique. Ils prennent comme entrée un ensemble de 0 arguments ou plus et retournent une seule valeur de sortie. Il n’existe aucune résolution de surcharge et aucune métadonnées concernant les noms de paramètres, les types ou les attentes.

L’interface IModelMethod est définie comme suit :

DECLARE_INTERFACE_(IModelMethod, IUnknown)
{
    STDMETHOD(Call)(_In_opt_ IModelObject *pContextObject, _In_ ULONG64 argCount, _In_reads_(argCount) IModelObject **ppArguments, _COM_Errorptr_ IModelObject **ppResult, _COM_Outptr_opt_result_maybenull_ IKeyStore **ppMetadata) PURE;
}

Appeler

La méthode Call est la façon dont toute méthode définie dans le modèle de données est appelée. L’appelant est responsable de la transmission d’un objet instance précis (ce pointeur) et d’un ensemble arbitraire d’arguments. Le résultat de la méthode et toutes les métadonnées facultatives associées à ce résultat sont retournés. Les méthodes qui ne retournent pas logiquement une valeur doivent toujours retourner un IModelObject valide. Dans ce cas, IModelObject est une valeur non encadrée. En cas d’échec d’une méthode, elle peut retourner des informations d’erreur étendues facultatives dans l’argument d’entrée (même si le HRESULT retourné est un échec). Il est impératif que les appelants case activée pour cela.

Références clés : IModelKeyReference ou IModelKeyReference2

Une référence de clé est, par essence, un handle à une clé sur un objet particulier. Un client peut récupérer ce handle via des méthodes telles que GetKeyReference et utiliser le handle ultérieurement pour obtenir ou définir la valeur de la clé sans nécessairement conserver l’objet d’origine. Ce type d’objet est une implémentation de l’interface IModelKeyReference ou IModelKeyReference2 qui est boxée dans un IModelObject. L’objet de modèle retourne une sorte d’ObjectKeyReference lorsqu’il est interrogé, puis la valeur intrinsèque est une VT_UNKNOWN qui est garantie d’être interrogeable pour IModelKeyReference. En cours de traitement, il est garanti d’être castable statiquement en IModelKeyReference.

L’interface de référence de clé est définie comme suit :

DECLARE_INTERFACE_(IModelKeyReference2, IModelKeyReference)
{
    STDMETHOD(GetKeyName)(_Out_ BSTR* keyName) PURE;
    STDMETHOD(GetOriginalObject)(_COM_Outptr_ IModelObject** originalObject) PURE;
    STDMETHOD(GetContextObject)(_COM_Outptr_ IModelObject** containingObject) PURE;
    STDMETHOD(GetKey)(_COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(GetKeyValue)(_COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(SetKey)(_In_opt_ IModelObject* object, _In_opt_ IKeyStore* metadata) PURE;
    STDMETHOD(SetKeyValue)(_In_ IModelObject* object) PURE;
    STDMETHOD(OverrideContextObject)(_In_ IModelObject* newContextObject) PURE;
}

GetKeyName

La méthode GetKeyName retourne le nom de la clé à laquelle cette référence de clé est un handle. La chaîne retournée est un BSTR standard et doit être libérée via un appel à SysFreeString.

GetOriginalObject

La méthode GetOriginalObject retourne l’objet instance à partir duquel la référence de clé a été créée. Notez que la clé peut se trouver elle-même sur un modèle parent de l’objet instance.

GetContextObject

La méthode GetContextObject retourne le contexte (ce pointeur) qui sera passé à la méthode GetValue ou SetValue d’un accesseur de propriété si la clé en question fait référence à un accesseur de propriété. L’objet de contexte retourné ici peut ou non être identique à l’objet d’origine extrait de GetOriginalObject. Si une clé se trouve sur un modèle parent et qu’un ajusteur de contexte est associé à ce modèle parent, l’objet d’origine est l’objet instance sur lequel GetKeyReference ou EnumerateKeyReferences a été appelé. L’objet de contexte est ce qui sort de l’ajusteur de contexte final entre l’objet d’origine et le modèle parent contenant la clé pour laquelle cette référence de clé est un handle. S’il n’existe pas d’ajusteurs de contexte, l’objet d’origine et l’objet de contexte sont identiques.

GetKey

La méthode GetKey sur une référence de clé se comporte comme la méthode GetKey sur IModelObject. Il retourne la valeur de la clé sous-jacente et toutes les métadonnées associées à la clé. Si la valeur de la clé s’avère être un accesseur de propriété, cela retourne l’accesseur de propriété (IModelPropertyAccessor) boxé dans un IModelObject. Cette méthode n’appelle pas les méthodes GetValue ou SetValue sous-jacentes sur l’accesseur de propriété.

GetKeyValue

La méthode GetKeyValue sur une référence de clé se comporte comme la méthode GetKeyValue sur IModelObject. Il retourne la valeur de la clé sous-jacente et toutes les métadonnées associées à la clé. Si la valeur de la clé s’avère être un accesseur de propriété, cela appelle automatiquement la méthode GetValue sous-jacente sur l’accesseur de propriété.

SetKey

La méthode SetKey sur une référence de clé se comporte comme la méthode SetKey sur IModelObject. Il affectera la valeur de la clé. Si la clé d’origine était un accesseur de propriété, cela remplacera l’accesseur de propriété. Il n’appelle pas la méthode SetValue sur l’accesseur de propriété.

SetKeyValue

La méthode SetKeyValue sur une référence de clé se comporte comme la méthode SetKeyValue sur IModelObject. Il affectera la valeur de la clé. Si la clé d’origine était un accesseur de propriété, cela appelle la méthode SetValue sous-jacente sur l’accesseur de propriété au lieu de remplacer l’accesseur de propriété lui-même.

OverrideContextObject

La méthode OverrideContextObject (présente uniquement sur IModelKeyReference2) est une méthode avancée utilisée pour modifier définitivement l’objet de contexte que cette référence de clé passera aux méthodes GetValue ou SetValue de tout accesseur de propriété sous-jacent. L’objet passé à cette méthode est également retourné à partir d’un appel à GetContextObject. Cette méthode peut être utilisée par les fournisseurs de scripts pour répliquer certains comportements de langage dynamique. La plupart des clients ne doivent pas appeler cette méthode.

Objets de contexte : IDebugHostContext

Les objets de contexte sont des objets blob opaques d’informations que l’hôte de débogage (en coopération avec le modèle de données) associe à chaque objet. Il peut inclure des éléments tels que le contexte de processus ou l’espace d’adressage dont les informations proviennent, etc. Un objet de contexte est une implémentation de IDebugHostContext boxée dans un IModelObject. Notez que IDebugHostContext est une interface définie par l’hôte. Un client n’implémentera jamais cette interface.

Pour plus d’informations sur les objets de contexte, consultez Interfaces hôtes C++ du modèle de données du débogueur dans les interfaces C++ du modèle de données du débogueur.

Gestionnaire de modèle de données

L’interface principale du gestionnaire de modèle de données, IDataModelManager2 (ou IDataModelManager antérieur) est définie comme suit :

DECLARE_INTERFACE_(IDataModelManager2, IDataModelManager)
{
    //
    // IDataModelManager:
    //
    STDMETHOD(Close)() PURE;
    STDMETHOD(CreateNoValue)(_Out_ IModelObject** object) PURE;
    STDMETHOD(CreateErrorObject)(_In_ HRESULT hrError, _In_opt_ PCWSTR pwszMessage, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateTypedObject)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(CreateTypedObjectReference)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(CreateSyntheticObject)(_In_opt_ IDebugHostContext* context, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateDataModelObject)(_In_ IDataModelConcept* dataModel, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateIntrinsicObject)(_In_ ModelObjectKind objectKind, _In_ VARIANT* intrinsicData, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateTypedIntrinsicObject)(_In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(GetModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _Out_ IModelObject** dataModel) PURE;
    STDMETHOD(GetModelForType)(_In_ IDebugHostType* type, _COM_Outptr_ IModelObject** dataModel, _COM_Outptr_opt_ IDebugHostTypeSignature** typeSignature, _COM_Outptr_opt_ IDebugHostSymbolEnumerator** wildcardMatches) PURE;
    STDMETHOD(RegisterModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterModelForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(RegisterExtensionForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterExtensionForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(CreateMetadataStore)(_In_opt_ IKeyStore* parentStore, _COM_Outptr_ IKeyStore** metadataStore) PURE;
    STDMETHOD(GetRootNamespace)(_COM_Outptr_ IModelObject** rootNamespace) PURE;
    STDMETHOD(RegisterNamedModel)(_In_ PCWSTR modelName, _In_ IModelObject *modeObject) PURE;
    STDMETHOD(UnregisterNamedModel)(_In_ PCWSTR modelName) PURE;
    STDMETHOD(AcquireNamedModel)(_In_ PCWSTR modelName, _COM_Outptr_ IModelObject **modelObject) PURE;
    //
    // IDataModelManager2:
    //
    STDMETHOD(AcquireSubNamespace)(_In_ PCWSTR modelName, _In_ PCWSTR subNamespaceModelName, _In_ PCWSTR accessName, _In_opt_ IKeyStore *metadata, _COM_Outptr_ IModelObject **namespaceModelObject) PURE;
    STDMETHOD(CreateTypedIntrinsicObjectEx)(_In_opt_ IDebugHostContext* context, _In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;
}

Méthodes de gestion

L’ensemble de méthodes suivant est utilisé par l’application (par exemple, le débogueur) qui héberge le modèle de données.

STDMETHOD(Close)() PURE;

Close

La méthode Close est appelée sur le gestionnaire de modèle de données par une application (par exemple : débogueur) hébergeant le modèle de données afin de démarrer le processus d’arrêt du gestionnaire de modèle de données. Un hôte du modèle de données qui ne fait pas la méthode Close avant de publier sa référence finale sur le gestionnaire de modèle de données peut entraîner un comportement non défini, y compris, mais sans s’y limiter, des fuites importantes de l’infrastructure de gestion pour le modèle de données.

Création d’objets / Méthodes de boxe

L’ensemble de méthodes suivant est utilisé pour créer de nouveaux objets ou pour boxer des valeurs dans un IModelObject, l’interface principale du modèle de données.

STDMETHOD(CreateNoValue)(_Out_ IModelObject** object) PURE;
STDMETHOD(CreateErrorObject)(_In_ HRESULT hrError, _In_opt_ PCWSTR pwszMessage, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateTypedObject)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(CreateTypedObjectReference)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(CreateSyntheticObject)(_In_opt_ IDebugHostContext* context, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateDataModelObject)(_In_ IDataModelConcept* dataModel, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateIntrinsicObject)(_In_ ModelObjectKind objectKind, _In_ VARIANT* intrinsicData, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateTypedIntrinsicObject)(_In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateMetadataStore)(_In_opt_ IKeyStore* parentStore, _COM_Outptr_ IKeyStore** metadataStore) PURE;
STDMETHOD(CreateTypedIntrinsicObjectEx)(_In_opt_ IDebugHostContext* context, _In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;

CreateNoValue

La méthode CreateNoValue crée un objet « no value », le place dans un IModelObject et le retourne. L’objet de modèle retourné a un type ObjectNoValue.

Un objet « sans valeur » a plusieurs significations sémantiques :

  • (Selon la langue), il peut être considéré comme l’équivalent sémantique de void, null ou undefined
  • La méthode GetValue de tout accesseur de propriété qui retourne la réussite et un objet « aucune valeur » résultant indique que la propriété particulière n’a aucune valeur pour le instance donné et doit être traitée comme si la propriété n’existait pas pour ce instance particulier.
  • Les méthodes de modèle de données qui n’ont pas sémantiquement de valeur de retour l’utilisent comme sentinelle pour indiquer ce type (car une méthode doit retourner un IModelObject valide).

CreateErrorObject

La méthode CreateErrorObject crée un « objet d’erreur ». Le modèle de données n’a pas la notion d’exceptions et de flux d’exceptions. L’échec provient d’une propriété/méthode de deux manières :

  • Un SEUL HRESULT défaillant sans informations d’erreur étendues. Soit il n’y a plus d’informations qui peuvent être fournies pour l’erreur, soit l’erreur elle-même est explicite à partir du HRESULT retourné.
  • Un SEUL HRESULT défaillant associé à des informations d’erreur étendues. Les informations d’erreur étendues sont un objet d’erreur retourné dans l’argument de sortie de la propriété/méthode.

CreateTypedObject

La méthode CreateTypedObject est la méthode qui permet à un client de créer une représentation d’un objet natif/langage dans l’espace d’adressage d’une cible de débogage. Si le type de l’objet nouvellement créé (comme indiqué par l’argument objectType) correspond à une ou plusieurs signatures de type inscrites auprès du gestionnaire de modèle de données en tant que visualiseurs canoniques ou extensions, ces modèles de données correspondants sont automatiquement attachés à l’objet instance créé avant qu’il ne soit retourné à l’appelant.

CreateTypedObjectReference

La méthode CreateTypedObjectReference est sémantiquement similaire à la méthode CreateTypedObject, sauf qu’elle crée une référence à la construction native/de langage sous-jacente. La référence créée est un objet qui a une sorte de ObjectTargetObjectReference. Il ne s’agit pas d’une référence native que le langage sous-jacent peut prendre en charge (par exemple, un & C++ ou un &&). Il est tout à fait possible d’avoir un ObjectTargetObjectReference vers une référence C++. Un objet de type ObjectTargetObjectReference peut être converti en valeur sous-jacente à l’aide de la méthode Dereference sur IModelObject. La référence peut également être passée à l’évaluateur d’expression de l’hôte sous-jacent afin de l’affecter à la valeur dans une langue appropriée.

CreateSyntheticObject

La méthode CreateSyntheticObject crée un objet de modèle de données vide, un dictionnaire de tuples et de concepts clé/valeur/métadonnées. Au moment de la création, il n’y a pas de clés ni de concepts sur l’objet. Il s’agit d’une ardoise propre que l’appelant doit utiliser.

CreateDataModelObject

La méthode CreateDataModelObject est un wrapper d’assistance simple permettant de créer des objets qui sont des modèles de données, c’est-à-dire des objets qui vont être attachés en tant que modèles parents à d’autres objets. Tous ces objets doivent prendre en charge le concept de modèle de données via IDataModelConcept. Cette méthode crée un objet synthétique vide sans contexte explicite et ajoute le IDataModelConcept passé comme implémentation du concept de modèle de données par l’objet nouvellement créé. Cela peut également être effectué avec des appels à CreateSyntheticObject et SetConcept.

CreateIntrinsicObject

La méthode CreateIntrinsicObject est la méthode qui place des valeurs intrinsèques dans IModelObject. L’appelant place la valeur dans un VARIANT COM et appelle cette méthode. Le gestionnaire de modèle de données retourne un IModelObject représentant l’objet . Notez que cette méthode est également utilisée pour boxer des types fondamentaux basés sur IUnknown : accesseurs de propriété, méthodes, contextes, etc. Dans ce cas, la méthode objectKind indique le type de construction basée sur IUnknown que l’objet représente et le champ punkVal de la variante passée est le type dérivé IUnknown. Le type doit être statiquement castable pour l’interface de modèle appropriée (par exemple : IModelPropertyAccessor, IModelMethod, IDebugHostContext, etc...) en cours de traitement. Les types VARIANT pris en charge par cette méthode sont VT_UI1, VT_I1, VT_UI2, VT_I2, VT_UI4, VT_I4, VT_UI8, VT_I8, VT_R4, VT_R8, VT_BOOL, VT_BSTR et VT_UNKNOWN (pour un ensemble spécialisé de types dérivés IUnknown comme indiqué par l’énumération ModelObjectKind.

CreateTypedIntrinsicObject

La méthode CreateTypedintrinsicObject est similaire à la méthode CreateIntrinsicObject, sauf qu’elle permet à un type natif/de langue d’être associé aux données et porté avec la valeur encadrée. Cela permet au modèle de données de représenter des constructions telles que des types d’énumération natifs (qui sont simplement des valeurs VT_UI* ou VT_I*). Les types de pointeurs sont également créés avec cette méthode. Un pointeur natif dans le modèle de données est une quantité 64 bits étendue zéro représentant un décalage dans l’espace d’adressage virtuel de la cible de débogage. Il est encadré à l’intérieur d’un VT_UI8 et est créé avec cette méthode et un type qui indique un pointeur natif/de langue.

CreateMetadataStore

La méthode CreateMetadataStore crée un magasin de clés, un conteneur simplifié de tuples clé/valeur/métadonnées, qui est utilisé pour contenir les métadonnées qui peuvent être associées à des propriétés et à diverses autres valeurs. Un magasin de métadonnées peut avoir un parent unique (qui à son tour peut avoir un seul parent). Si une clé de métadonnées donnée ne se trouve pas dans un magasin donné, ses parents sont vérifiés. La plupart des magasins de métadonnées n’ont pas de parents. Toutefois, il fournit un moyen de partager facilement des métadonnées communes.

CreateTypedIntrinsicObjectEx

La méthode CreateTypedIntrinsicObjectEx est sémantiquement similaire à la méthode CreateTypedIntrinsicObject. La seule différence entre les deux est que cette méthode permet à l’appelant de spécifier le contexte dans lequel les données intrinsèques sont valides. Si aucun contexte n’est transmis, les données sont considérées comme valides dans n’importe quel contexte hérité de l’argument de type (comportement de CreateTypedIntrinsicObject). Cela permet de créer des valeurs de pointeur typées dans la cible de débogage qui nécessitent un contexte plus spécifique que celui qui peut être hérité du type.

Extensibilité /Méthodes d’inscription L’ensemble de méthodes suivant gère le mécanisme d’extensibilité du modèle de données, ce qui permet à un client d’étendre ou d’inscrire des modèles existants ou de demander au modèle de données d’attacher automatiquement un modèle parent donné sur des types natifs qui correspondent à un critère donné.

    STDMETHOD(GetModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _Out_ IModelObject** dataModel) PURE;
    STDMETHOD(GetModelForType)(_In_ IDebugHostType* type, _COM_Outptr_ IModelObject** dataModel, _COM_Outptr_opt_ IDebugHostTypeSignature** typeSignature, _COM_Outptr_opt_ IDebugHostSymbolEnumerator** wildcardMatches) PURE;
    STDMETHOD(RegisterModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterModelForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(RegisterExtensionForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterExtensionForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(GetRootNamespace)(_COM_Outptr_ IModelObject** rootNamespace) PURE;
    STDMETHOD(RegisterNamedModel)(_In_ PCWSTR modelName, _In_ IModelObject *modeObject) PURE;
    STDMETHOD(UnregisterNamedModel)(_In_ PCWSTR modelName) PURE;
    STDMETHOD(AcquireNamedModel)(_In_ PCWSTR modelName, _COM_Outptr_ IModelObject **modelObject) PURE;

GetModelForTypeSignature

La méthode GetModelForTypeSignature retourne le modèle de données qui a été inscrit par rapport à une signature de type particulière via un appel antérieur à la méthode RegisterModelForTypeSignature. Le modèle de données retourné par cette méthode est considéré comme le visualiseur canonique pour tout type qui correspond à la signature de type passée. En tant que visualiseur canonique, ce modèle de données prend le contrôle de l’affichage du type. Par défaut, les moteurs d’affichage masquent les constructions natives/linguistiques de l’objet au profit de la vue de l’objet présenté par le modèle de données.

GetModelForType

La méthode GetModelForType retourne le modèle de données qui est le visualiseur canonique pour un type donné instance. En effet, cette méthode recherche la meilleure signature de type correspondante qui a été inscrite avec un appel antérieur à la méthode RegisterModelForTypeSignature et retourne le modèle de données associé.

RegisterModelForTypeSignature

La méthode RegisterModelForTypeSignature est la méthode principale qu’un appelant utilise pour inscrire un visualiseur canonique pour un type (ou ensemble de types) donné. Un visualiseur canonique est un modèle de données qui, en effet, prend en charge l’affichage d’un type (ou d’un ensemble de types donné). Au lieu d’afficher la vue native/linguistique du type dans une interface utilisateur de débogueur, l’affichage du type tel que présenté par le modèle de données inscrit s’affiche (ainsi qu’un moyen de revenir à l’affichage natif/linguistique pour un utilisateur qui le souhaite).

UnregisterModelForTypeSignature

La méthode UnregisterModelForTypeSignature annule un appel antérieur à la méthode RegisterModelForTypeSignature. Cette méthode peut soit supprimer un modèle de données donné en tant que visualiseur canonique pour les types correspondant à une signature de type particulière, soit supprimer un modèle de données donné en tant que visualiseur canonique pour chaque signature de type sous laquelle ce modèle de données est inscrit.

RegisterExtensionForTypeSignature

La méthode RegisterExtensionForTypeSignature est similaire à la méthode RegisterModelForTypeSignature avec une différence clé. Le modèle de données qui est passé à cette méthode n’est pas le visualiseur canonique pour n’importe quel type et il ne prend pas en charge l’affichage de la vue native/linguistique de ce type. Le modèle de données passé à cette méthode est automatiquement ajouté en tant que parent à tout type concret qui correspond à la signature de type fournie. Contrairement à la méthode RegisterModelForTypeSignature, il n’existe aucune limite pour les signatures de type identiques ou ambiguës inscrites en tant qu’extensions d’un type (ou d’un ensemble de types donné). Chaque extension dont la signature de type correspond à un type concret donné instance entraîne l’attachement automatique du modèle de données inscrit via cette méthode aux objets nouvellement créés en tant que modèles parent. Cela, en effet, permet à un nombre arbitraire de clients d’étendre un type (ou un ensemble de types) avec de nouveaux champs ou fonctionnalités.

UnregisterExtensionForTypeSignature

La méthode UnregisterExtensionForTypeSignature annule un appel antérieur à RegisterExtensionForTypeSignature. Il annule l’inscription d’un modèle de données particulier en tant qu’extension pour une signature de type particulière ou en tant qu’extension pour toutes les signatures de type sur lesquelles le modèle de données a été inscrit.

GetRootNamespace

La méthode GetRootNamespace retourne l’espace de noms racine du modèle de données. Il s’agit d’un objet que le modèle de données gère et dans lequel l’hôte de débogage place certains objets.

RegisterNamedModel

La méthode RegisterNamedModel inscrit un modèle de données donné sous un nom bien connu afin qu’il puisse être trouvé par les clients souhaitant l’étendre. Il s’agit de l’objectif principal de l’API : publier un modèle de données en tant que quelque chose qui peut être étendu en récupérant le modèle inscrit sous ce nom bien connu et en y ajoutant un modèle parent.

UnregisterNamedModel

La méthode UnregisterNamedModel annule un appel précédent à RegisterNamedModel. Il supprime l’association entre un modèle de données et un nom sous lequel il peut être recherché.

AcquireNamedModel

Un appelant qui souhaite étendre un modèle de données inscrit sous un nom donné appelle la méthode AcquireNamedModel afin de récupérer l’objet du modèle de données qu’il souhaite étendre. Cette méthode retourne tout modèle de données inscrit via un appel précédent à la méthode RegisterNamedModel. Étant donné que l’objectif principal de la méthode AcquireNamedModel est d’étendre le modèle, cette méthode a un comportement spécial si aucun modèle n’a encore été inscrit sous le nom donné. Si aucun modèle n’a encore été inscrit sous le nom donné, un objet stub est créé, inscrit temporairement sous le nom donné et retourné à l’appelant. Lorsque le modèle de données réel est inscrit via un appel à la méthode RegisterNamedModel, toutes les modifications apportées à l’objet stub sont, en effet, apportées au modèle réel. Cela supprime de nombreux problèmes de dépendance d’ordre de chargement des composants qui s’étendent les uns les autres.

Méthodes d'assistance

Les méthodes suivantes sont des méthodes d’assistance générales qui permettent d’effectuer des opérations complexes sur des objets dans le modèle de données. Bien qu’il soit possible d’effectuer ces actions via d’autres méthodes sur le modèle de données ou ses objets, ces méthodes pratiques facilitent considérablement la tâche :

STDMETHOD(AcquireSubNamespace)(_In_ PCWSTR modelName, _In_ PCWSTR subNamespaceModelName, _In_ PCWSTR accessName, _In_opt_ IKeyStore *metadata, _COM_Outptr_ IModelObject **namespaceModelObject) PURE;

AcquireSubNamespace

La méthode AcquireSubNamespace aide à construire quelque chose qui peut ressembler plus traditionnellement à un espace de noms de langage qu’à un nouvel objet dans un langage dynamique. Si, par instance, un appelant souhaite catégoriser les propriétés d’un objet de processus afin de rendre l’objet de processus plus organisé et les propriétés plus faciles à découvrir, une méthode consiste à créer un sous-objet pour chaque catégorie sur l’objet de processus et à placer ces propriétés à l’intérieur de cet objet.

Voir aussi

Cette rubrique fait partie d’une série qui décrit les interfaces accessibles à partir de C++, comment les utiliser pour créer une extension de débogueur basée sur C++ et comment utiliser d’autres constructions de modèles de données (par exemple, JavaScript ou NatVis) à partir d’une extension de modèle de données C++.

Vue d’ensemble du modèle de données C++ du débogueur

Interfaces C++ du modèle de données du débogueur

Interfaces supplémentaires du modèle de données C++ du débogueur

Concepts du modèle de données C++ du débogueur

Script C++ du modèle de données du débogueur