Interface IMarshal (objidlbase.h)
Permet à un objet COM de définir et gérer le marshaling de ses pointeurs d'interface.
Héritage
L’interface IMarshal hérite de l’interface IUnknown. IMarshal a également les types de membres suivants :
Méthodes
L’interface IMarshal a ces méthodes.
IMarshal ::D isconnectObject La méthode IMarshal ::D isconnectObject (objidlbase.h) libère toutes les connexions à un objet dont le serveur appelle l’implémentation de cette méthode par l’objet. |
IMarshal ::MarshalInterface La méthode IMarshal ::MarshalInterface (objidlbase.h) marshale un pointeur d’interface. |
IMarshal ::ReleaseMarshalData La méthode IMarshal ::ReleaseMarshalData (objidlbase.h) détruit un paquet de données marshalé. |
IMarshal ::UnmarshalInterface La méthode IMarshal ::UnmarshalInterface (objidlbase.h) désactive un pointeur d’interface. |
Remarques
Le marshaling est le processus d’empaquetage des données dans des paquets pour les transmettre à un autre processus ou ordinateur. Unmarshaling est le processus de récupération de ces données à la fin de la réception. Dans un appel donné, les arguments de méthode sont marshalés et non délimités dans une direction, tandis que les valeurs de retour sont marshalées et non délimitées dans l’autre.
Bien que le marshaling s’applique à tous les types de données, les pointeurs d’interface nécessitent une gestion spéciale. Le problème fondamental est la façon dont le code client s’exécutant dans un espace d’adressage peut déréférencer correctement un pointeur vers une interface sur un objet résidant dans un autre espace d’adressage. La solution COM permet à une application cliente de communiquer avec l’objet d’origine par le biais d’un objet de substitution, ou proxy, qui réside dans le processus du client. Le proxy contient une référence à une interface sur l’objet d’origine et remet au client un pointeur vers une interface sur lui-même. Lorsque le client appelle une méthode d’interface sur l’objet d’origine, son appel est en fait destiné au proxy. Par conséquent, du point de vue du client, tous les appels sont en cours.
Lors de la réception d’un appel, le proxy marshale les arguments de méthode et par le biais de certains moyens de communication interprocess, tels que RPC, les transmet au code dans le processus serveur, ce qui démarshale les arguments et les transmet à l’objet d’origine. Ce même code marshale les valeurs pour la transmission au proxy, ce qui déséchante les valeurs et les transmet à l’application cliente.
IMarshal fournit des méthodes pour créer, initialiser et gérer un proxy dans un processus client ; il ne dicte pas la façon dont le proxy doit communiquer avec l’objet d’origine. L’implémentation COM par défaut d’IMarshal utilise RPC. Lorsque vous implémentez cette interface vous-même, vous êtes libre de choisir n’importe quelle méthode de communication entre processus que vous jugez appropriée pour votre application (mémoire partagée, canal nommé, handle de fenêtre, RPC) en bref, quel que soit le fonctionnement.
Implémentation par défaut IMarshal
COM utilise sa propre implémentation interne de l’interface IMarshal pour marshaler tout objet qui ne fournit pas sa propre implémentation. COM effectue cette détermination en interrogeant l’objet pour IMarshal. Si l’interface est manquante, COM utilise par défaut son implémentation interne.L’implémentation COM par défaut d’IMarshal utilise un proxy générique pour chaque objet et crée des stubs et des proxys individuels, en fonction des besoins, pour chaque interface implémentée sur l’objet. Ce mécanisme est nécessaire, car COM ne peut pas savoir à l’avance quelles interfaces particulières un objet donné peut implémenter. Les développeurs qui n’utilisent pas le marshaling COM par défaut, choisissant à la place d’écrire leurs propres routines de proxy et de marshaling, connaissent au moment de la compilation toutes les interfaces à trouver sur leurs objets et comprennent donc exactement quel code de marshaling est requis. COM, en fournissant la prise en charge du marshaling pour tous les objets, doit le faire au moment de l’exécution.
Le proxy d’interface réside dans le processus client ; le stub d’interface réside dans le serveur. Ensemble, chaque paire gère tout le marshaling pour l’interface. Le travail de chaque proxy d’interface consiste à marshaler les arguments et à démarshaler les valeurs de retour et les paramètres sortants qui sont passés dans les appels suivants à son interface. Le travail de chaque stub d’interface consiste à démarshaler les arguments de fonction et à les transmettre à l’objet d’origine, puis à marshaler les valeurs de retour et les paramètres sortants que l’objet retourne.
Le proxy et le stub communiquent au moyen d’un canal RPC (appel de procédure distante), qui utilise l’infrastructure RPC du système pour la communication interprocess. Le canal RPC implémente une interface unique, IRpcChannelBuffer, vers laquelle les proxys et les stubs d’interface contiennent un pointeur. Le proxy et le stub appellent l’interface pour obtenir un paquet de marshaling, envoyer les données à leur équivalent et détruire le paquet quand ils sont terminés. Le stub d’interface contient également un pointeur vers l’objet d’origine.
Pour une interface donnée, le proxy et le stub sont tous deux implémentés en tant qu’instances de la même classe, qui est répertoriée pour chaque interface dans le registre système sous l’étiquette ProxyStubClsid32. Cette entrée mappe l’IID de l’interface au CLSID de ses objets proxy et stub. Lorsque COM doit marshaler une interface, il recherche dans le registre système pour obtenir le CLSID approprié. Le serveur identifié par ce CLSID implémente à la fois le proxy d’interface et le stub d’interface.
Le plus souvent, la classe à laquelle fait référence ce CLSID est générée automatiquement par un outil dont l’entrée est une description des signatures de fonction et de la sémantique d’une interface donnée, écrite dans un langage de description d’interface donné. Bien que l’utilisation d’une telle langue soit fortement recommandée et encouragée par souci d’exactitude, cela n’est pas obligatoire. Les proxys et les stubs sont simplement des composants COM utilisés par l’infrastructure RPC et, en tant que tels, peuvent être écrits de la manière souhaitée, tant que les contrats externes corrects sont respectés. Le programmeur qui conçoit une nouvelle interface est chargé de s’assurer que tous les proxys et stubs d’interface qui existent sont d’accord sur la représentation de leurs données marshalées.
Une fois créés, les proxys d’interface sont toujours agrégés dans un proxy plus grand, qui représente l’objet dans son ensemble. Ce proxy d’objet agrège également l’objet proxy générique COM, connu sous le nom de gestionnaire de proxy. Le gestionnaire de proxy implémente deux interfaces : IUnknown et IMarshal. Toutes les autres interfaces qui peuvent être implémentées sur un objet sont exposées dans son proxy d’objet via l’agrégation de proxys d’interface individuels. Un client qui contient un pointeur vers le proxy d’objet « croit » qu’il contient un pointeur vers l’objet réel.
Un proxy représentant l’objet dans son ensemble est requis dans le processus client afin qu’un client puisse distinguer les appels aux mêmes interfaces implémentées sur des objets entièrement différents. Une telle exigence n’existe pas dans le processus serveur, cependant, où réside l’objet lui-même, car tous les stubs d’interface communiquent uniquement avec les objets pour lesquels ils ont été créés. Aucune autre connexion n’est possible.
Contrairement aux proxys d’interface, les stubs d’interface ne sont pas agrégés, car il n’est pas nécessaire qu’un client externe apparaisse comme faisant partie d’un ensemble plus grand. Lorsqu’il est connecté, un stub d’interface reçoit un pointeur vers l’objet serveur vers lequel il doit transférer les appels de méthode qu’il reçoit. Bien qu’il soit utile de faire référence conceptuellement à un gestionnaire de stub, c’est-à-dire tous les éléments de code et d’état de l’infrastructure RPC côté serveur qui prennent en charge la communication à distance d’un objet donné, il n’est pas nécessaire que le code et l’état prennent une forme particulière et bien spécifiée.
La première fois qu’un client demande un pointeur vers une interface sur un objet particulier, COM charge un stub IClassFactory dans le processus serveur et l’utilise pour marshaler le premier pointeur vers le client. Dans le processus client, COM charge le proxy générique pour l’objet de fabrique de classe et appelle son implémentation d’IMarshal pour annuler ce premier pointeur. COM crée ensuite le premier proxy d’interface et lui remet un pointeur vers le canal RPC. Enfin, COM retourne le pointeur IClassFactory vers le client, qui l’utilise pour appeler IClassFactory ::CreateInstance, en lui transmettant une référence à l’interface.
De retour dans le processus serveur, COM crée maintenant une nouvelle instance de l’objet, ainsi qu’un stub pour l’interface demandée. Ce stub marshale le pointeur d’interface vers le processus client, où un autre proxy d’objet est créé, cette fois pour l’objet lui-même. Est également créé un proxy pour l’interface demandée, un pointeur vers lequel est retourné au client. Avec les appels suivants à d’autres interfaces sur l’objet, COM charge les stubs d’interface et les proxys appropriés si nécessaire.
Lorsqu’un proxy d’interface est créé, COM lui remet un pointeur vers l’implémentation par le gestionnaire de proxy d’IUnknown, à laquelle il délègue tous les appels QueryInterface . Chaque proxy d’interface implémente ses propres interfaces : l’interface qu’il représente et IRpcProxyBuffer. Le proxy d’interface expose sa propre interface directement aux clients, qui peuvent obtenir son pointeur en appelant QueryInterface sur le gestionnaire de proxy. Toutefois, seul COM peut appeler IRpcProxyBuffer, qui est utilisé pour connecter et déconnecter le proxy au canal RPC. Un client ne peut pas interroger un proxy d’interface pour obtenir un pointeur vers l’interface IRpcProxyBuffer .
Côté serveur, chaque stub d’interface implémente IRpcStubBuffer. Le code du serveur agissant comme un gestionnaire de stub appelle IRpcStubBuffer ::Connect et transmet le stub d’interface au pointeur IUnknown de son objet.
Lorsqu’un proxy d’interface reçoit un appel de méthode, il obtient un paquet de marshaling à partir de son canal RPC via un appel à IRpcChannelBuffer ::GetBuffer. Le processus de marshaling des arguments copiera les données dans la mémoire tampon. Une fois le marshaling terminé, le proxy d’interface appelle IRpcChannelBuffer ::SendReceive pour envoyer le paquet marshalé au stub d’interface correspondant. Quand IRpcChannelBuffer ::SendReceive retourne, la mémoire tampon dans laquelle les arguments ont été marshalés a été remplacée par une nouvelle mémoire tampon contenant les valeurs de retour marshalées à partir du stub d’interface. Le proxy d’interface désactive les valeurs de retour, appelle IRpcChannelBuffer ::FreeBuffer pour libérer la mémoire tampon, puis retourne les valeurs de retour à l’appelant d’origine de la méthode.
C’est l’implémentation de IRpcChannelBuffer ::SendReceive qui envoie la demande au processus serveur et qui sait comment identifier le processus serveur et, dans ce processus, l’objet auquel la demande doit être envoyée. L’implémentation du canal sait également comment transférer la demande au gestionnaire de stub approprié dans ce processus. Le stub d’interface désactive les arguments de la mémoire tampon fournie, appelle la méthode indiquée sur l’objet serveur et marshale les valeurs de retour dans une nouvelle mémoire tampon allouée par un appel à IRpcChannelBuffer ::GetBuffer. Le canal transmet ensuite le paquet de données de retour au proxy d’interface, qui se trouve toujours au milieu de IRpcChannelBuffer ::SendReceive, qui retourne au proxy d’interface.
Un instance particulier d’un proxy d’interface peut être utilisé pour traiter plusieurs interface, tant que les conditions suivantes sont remplies :
- Les ID IID des interfaces affectées doivent être mappés au ProxyStubClsid approprié dans le registre système.
- Le proxy d’interface doit prendre en charge les appels à QueryInterface à partir d’une interface prise en charge vers les autres interfaces, comme d’habitude, ainsi que depuis IUnknown et IRpcProxyBuffer.
À différents moments, les proxys et les stubs devront allouer ou libérer de la mémoire. Les proxys d’interface, par exemple, devront allouer de la mémoire pour retourner les paramètres à leur appelant. À cet égard, les proxys d’interface et les stubs d’interface ne sont que des composants COM normaux, dans la mesure où ils doivent utiliser l’allocateur de tâche standard. (Voir CoGetMalloc.)
Configuration requise
Condition requise | Valeur |
---|---|
Client minimal pris en charge | Windows 2000 Professionnel [applications de bureau | Applications UWP] |
Serveur minimal pris en charge | Windows 2000 Server [applications de bureau | Applications UWP] |
Plateforme cible | Windows |
En-tête | objidlbase.h (inclure ObjIdl.h) |