IMarshal-Schnittstelle (objidl.h)
Ermöglicht einem COM-Objekt, das Marshalling der Schnittstellenzeiger zu definieren und zu verwalten.
Vererbung
Die IMarshal-Schnittstelle erbt von der IUnknown-Schnittstelle . IMarshal verfügt auch über folgende Arten von Mitgliedern:
Methoden
Die IMarshal-Schnittstelle verfügt über diese Methoden.
IMarshal::D isconnectObject Die IMarshal::D isconnectObject-Methode (objidl.h) gibt vor dem Herunterfahren alle Verbindungen mit einem Objekt frei. |
IMarshal::GetMarshalSizeMax Ruft die maximale Größe des Puffers ab, die während des Marshallvorgangs benötigt wird. |
IMarshal::GetUnmarshalClass Ruft die CLSID des entmarshaling-Codes ab. |
IMarshal::MarshalInterface Die IMarshal::MarshalInterface-Methode (objidl.h) marshallt einen Schnittstellenzeiger. |
IMarshal::ReleaseMarshalData Die IMarshal::ReleaseMarshalData-Methode (objidl.h) zerstört ein gemarschtes Datenpaket. |
IMarshal::UnmarshalInterface Die IMarshal::UnmarshalInterface-Methode (objidl.h) entmarshaliert einen Schnittstellenzeiger. |
Hinweise
Marshalling ist der Prozess des Verpackens von Daten in Pakete für die Übertragung an einen anderen Prozess oder Computer. Die Entmarstung ist der Prozess der Wiederherstellung dieser Daten am empfangenden Ende. Bei jedem gegebenen Aufruf werden Methodenargumente gemarst und in einer Richtung nichtmarshaliert, während Rückgabewerte gemarst und in der anderen Richtung entmarshaliert werden.
Obwohl Marshalling für alle Datentypen gilt, erfordern Schnittstellenzeiger eine besondere Behandlung. Das grundlegende Problem besteht darin, wie Clientcode, der in einem Adressraum ausgeführt wird, einen Zeiger auf eine Schnittstelle für ein Objekt, das sich in einem anderen Adressraum befindet, ordnungsgemäß ableiten kann. Bei der COM-Lösung kann eine Clientanwendung mit dem ursprünglichen Objekt über ein Ersatzobjekt oder einen Proxy kommunizieren, der sich im Clientprozess befindet. Der Proxy enthält einen Verweis auf eine Schnittstelle im ursprünglichen Objekt und übergibt dem Client einen Zeiger auf eine Schnittstelle an sich selbst. Wenn der Client eine Schnittstellenmethode für das ursprüngliche Objekt aufruft, geht ihr Aufruf tatsächlich an den Proxy. Aus Sicht des Clients werden daher alle Aufrufe in Bearbeitung ausgeführt.
Beim Empfangen eines Aufrufs überträgt der Proxy die Methodenargumente und über einige Mittel der Interprozesskommunikation, z. B. RPC, an Code im Serverprozess, wodurch die Argumente entmarshaliert und an das ursprüngliche Objekt übergeben werden. Dieselben Code-Marshalls geben Werte für die Übertragung zurück an den Proxy zurück, wodurch die Werte entmarshaliert und an die Clientanwendung übergeben werden.
IMarshal bietet Methoden zum Erstellen, Initialisieren und Verwalten eines Proxys in einem Clientprozess. es gibt nicht vor, wie der Proxy mit dem ursprünglichen Objekt kommunizieren soll. Die COM-Standardimplementierung von IMarshal verwendet RPC. Wenn Sie diese Schnittstelle selbst implementieren, können Sie jede Methode der Interprozesskommunikation auswählen, die Sie für Ihre Anwendung geeignet halten – shared memory, named pipe, window handle, RPC – kurz gesagt, was funktioniert.
IMarshal-Standardimplementierung
COM verwendet seine eigene interne Implementierung der IMarshal-Schnittstelle , um jedes Objekt zu marshallen, das keine eigene Implementierung bereitstellt. COM trifft diese Bestimmung, indem das Objekt für IMarshal abfragt. Wenn die Schnittstelle fehlt, verwendet COM standardmäßig die interne Implementierung.Die COM-Standardimplementierung von IMarshal verwendet einen generischen Proxy für jedes Objekt und erstellt je nach Bedarf einzelne Stubs und Proxys für jede im Objekt implementierte Schnittstelle. Dieser Mechanismus ist erforderlich, da COM nicht im Voraus wissen kann, welche bestimmten Schnittstellen ein bestimmtes Objekt implementieren kann. Entwickler, die kein COM-Standard marshaling verwenden und stattdessen ihre eigenen Proxy- und Marshallroutinen schreiben möchten, kennen zur Kompilierzeit alle Schnittstellen, die auf ihren Objekten zu finden sind, und wissen daher genau, welcher Marshallingcode erforderlich ist. COM muss bei der Bereitstellung von Marshallingunterstützung für alle Objekte dies zur Laufzeit tun.
Der Schnittstellenproxy befindet sich im Clientprozess. der Schnittstellenstub befindet sich auf dem Server. Zusammen verarbeitet jedes Paar das gesamte Marshalling für die Schnittstelle. Die Aufgabe jedes Schnittstellenproxys besteht darin, Argumente zu marshallen und werte und Parameter wieder aufzuheben, die bei nachfolgenden Aufrufen der Schnittstelle hin- und hergereicht werden. Die Aufgabe jedes Schnittstellenstubs besteht darin, Funktionsargumente aufzuheben und sie an das ursprüngliche Objekt zu übergeben und dann die Rückgabewerte und die vom Objekt zurückgegebenen Parameter zu marshallen.
Proxy und Stub kommunizieren über einen RPC-Kanal (Remoteprozeduraufruf), der die RPC-Infrastruktur des Systems für die Interprozesskommunikation nutzt. Der RPC-Kanal implementiert eine einzelne Schnittstelle, IRpcChannelBuffer, auf die sowohl Schnittstellenproxys als auch Stubs einen Zeiger enthalten. Der Proxy und der Stub rufen die Schnittstelle auf, um ein Marshallpaket zu erhalten, die Daten an ihre Entsprechung zu senden und das Paket zu zerstören, wenn sie fertig sind. Der Schnittstellenstub enthält auch einen Zeiger auf das ursprüngliche Objekt.
Für jede beliebige Schnittstelle werden der Proxy und der Stub als Instanzen derselben Klasse implementiert, die für jede Schnittstelle in der Systemregistrierung unter der Bezeichnung ProxyStubClsid32 aufgeführt ist. Dieser Eintrag ordnet die IID der Schnittstelle der CLSID ihrer Proxy- und Stubobjekte zu. Wenn COM eine Schnittstelle marshallen muss, sucht es in der Systemregistrierung, um die entsprechende CLSID abzurufen. Der durch diese CLSID identifizierte Server implementiert sowohl den Schnittstellenproxy als auch den Schnittstellenstub.
In den meisten Fällen wird die Klasse, auf die sich diese CLSID bezieht, automatisch von einem Tool generiert, dessen Eingabe eine Beschreibung der Funktionssignaturen und Semantik einer bestimmten Schnittstelle ist, die in einer Schnittstellenbeschreibungssprache geschrieben wird. Obwohl die Verwendung einer solchen Sprache aus Gründen der Genauigkeit dringend empfohlen und empfohlen wird, ist dies nicht erforderlich. Proxys und Stubs sind lediglich COM-Komponenten, die von der RPC-Infrastruktur verwendet werden und daher beliebig geschrieben werden können, solange die richtigen externen Verträge eingehalten werden. Der Programmierer, der eine neue Schnittstelle entwirft, ist dafür verantwortlich, dass sich alle Schnittstellenproxys und Stubs, die jemals vorhanden sind, über die Darstellung ihrer gemarselten Daten einig sind.
Beim Erstellen werden Schnittstellenproxys immer zu einem größeren Proxy aggregiert, der das Objekt als Ganzes darstellt. Dieser Objektproxy aggregiert auch das generische COM-Proxyobjekt, das als Proxy-Manager bezeichnet wird. Der Proxy-Manager implementiert zwei Schnittstellen: IUnknown und IMarshal. Alle anderen Schnittstellen, die für ein Objekt implementiert werden können, werden im Objektproxy über die Aggregation einzelner Schnittstellenproxys verfügbar gemacht. Ein Client, der einen Zeiger auf den Objektproxy hält, "glaubt", dass er einen Zeiger auf das tatsächliche Objekt enthält.
Ein Proxy, der das Objekt als Ganzes darstellt, ist im Clientprozess erforderlich, damit ein Client Aufrufe derselben Schnittstellen unterscheiden kann, die für völlig unterschiedliche Objekte implementiert sind. Eine solche Anforderung besteht jedoch nicht im Serverprozess, wo sich das Objekt selbst befindet, da alle Schnittstellenstubbs nur mit den Objekten kommunizieren, für die sie erstellt wurden. Eine andere Verbindung ist nicht möglich.
Schnittstellenstubbs werden im Gegensatz zu Schnittstellenproxys nicht aggregiert, da es nicht erforderlich ist, dass sie einem externen Client als Teil eines größeren Ganzen erscheinen. Wenn eine Verbindung hergestellt wird, erhält ein Schnittstellenstub einen Zeiger auf das Serverobjekt, auf das er Die Methodenaufrufe weiterleiten soll, die er empfängt. Obwohl es sinnvoll ist, konzeptuell auf einen Stub-Manager zu verweisen, d. h. auf jeden Code und Zustand in der serverseitigen RPC-Infrastruktur, die das Remoting eines bestimmten Objekts bedienen, müssen Code und Zustand keine bestimmte, wohldeutete Form annehmen.
Wenn ein Client zum ersten Mal einen Zeiger auf eine Schnittstelle für ein bestimmtes Objekt anfordert, lädt COM einen IClassFactory-Stub im Serverprozess und verwendet ihn, um den ersten Zeiger zurück an den Client zu marshallen. Im Clientprozess lädt COM den generischen Proxy für das Factoryobjekt der Klasse und ruft die Implementierung von IMarshal auf, um den ersten Zeiger zu entmarshalieren. COM erstellt dann den ersten Schnittstellenproxy und übergibt ihn einen Zeiger auf den RPC-Kanal. Schließlich gibt COM den IClassFactory-Zeiger auf den Client zurück, der ihn verwendet, um IClassFactory::CreateInstance aufzurufen und einen Verweis auf die Schnittstelle zu übergeben.
Zurück im Serverprozess erstellt COM nun eine neue instance des Objekts zusammen mit einem Stub für die angeforderte Schnittstelle. Dieser Stub marshallt den Schnittstellenzeiger zurück zum Clientprozess, in dem ein anderer Objektproxy erstellt wird, diesmal für das Objekt selbst. Außerdem wird ein Proxy für die angeforderte Schnittstelle erstellt, ein Zeiger, auf den an den Client zurückgegeben wird. Bei nachfolgenden Aufrufen anderer Schnittstellen für das Objekt lädt COM die entsprechenden Schnittstellen-Stubs und Proxys nach Bedarf.
Wenn ein neuer Schnittstellenproxy erstellt wird, übergibt COM einen Zeiger auf die Implementierung von IUnknown des Proxy-Managers, an die alle QueryInterface-Aufrufe delegiert werden. Jeder Schnittstellenproxy implementiert zwei eigene Schnittstellen: die Schnittstelle, die er darstellt, und IRpcProxyBuffer. Der Schnittstellenproxy macht seine eigene Schnittstelle direkt für Clients verfügbar, die ihren Zeiger abrufen können, indem QueryInterface im Proxy-Manager aufgerufen wird. Nur COM kann jedoch IRpcProxyBuffer aufrufen, das verwendet wird, um den Proxy mit dem RPC-Kanal zu verbinden und zu trennen. Ein Client kann keinen Schnittstellenproxy abfragen, um einen Zeiger auf die IRpcProxyBuffer-Schnittstelle abzurufen.
Auf der Serverseite implementiert jeder Schnittstellenstub IRpcStubBuffer. Der Servercode, der als Stub-Manager fungiert, ruft IRpcStubBuffer::Connect auf und übergibt den Schnittstellenstub den IUnknown-Zeiger des Objekts.
Wenn ein Schnittstellenproxy einen Methodenaufruf empfängt, ruft er über einen Aufruf von IRpcChannelBuffer::GetBuffer ein Marshallpaket von seinem RPC-Kanal ab. Beim Marshallen der Argumente werden Daten in den Puffer kopiert. Nach Abschluss des Marshallvorgangs ruft der Schnittstellenproxy IRpcChannelBuffer::SendReceive auf, um das gemarselte Paket an den entsprechenden Schnittstellenstub zu senden. Wenn IRpcChannelBuffer::SendReceive zurückgibt, wurde der Puffer, in den die Argumente ge marshallt wurden, durch einen neuen Puffer ersetzt, der die Rückgabewerte enthält, die aus dem Schnittstellenstub gemarst wurden. Der Schnittstellenproxy hebt die Rückgabewerte auf, ruft IRpcChannelBuffer::FreeBuffer auf, um den Puffer freizugeben, und gibt dann die Rückgabewerte an den ursprünglichen Aufrufer der Methode zurück.
Es ist die Implementierung von IRpcChannelBuffer::SendReceive , die die Anforderung tatsächlich an den Serverprozess sendet und weiß, wie der Serverprozess und innerhalb dieses Prozesses das Objekt identifiziert werden, an das die Anforderung gesendet werden soll. Die Kanalimplementierung weiß auch, wie die Anforderung in diesem Prozess an den entsprechenden Stub-Manager weitergeleitet werden kann. Der Schnittstellenstub entmarshaliert die Argumente aus dem bereitgestellten Puffer, ruft die angegebene Methode für das Serverobjekt auf und marshallt die Rückgabewerte zurück in einen neuen Puffer, der durch einen Aufruf von IRpcChannelBuffer::GetBuffer zugeordnet wird. Der Kanal überträgt dann das Rückgabedatenpaket zurück an den Schnittstellenproxy, der sich noch in der Mitte von IRpcChannelBuffer::SendReceive befindet und an den Schnittstellenproxy zurückgibt.
Ein bestimmter instance eines Schnittstellenproxys kann verwendet werden, um mehrere Schnittstellen zu warten, solange die folgenden Bedingungen erfüllt sind:
- Die IIDs der betroffenen Schnittstellen müssen der entsprechenden ProxyStubClsid in der Systemregistrierung zugeordnet werden.
- Der Schnittstellenproxy muss Wie gewohnt Aufrufe von QueryInterface von einer unterstützten Schnittstelle zu den anderen Schnittstellen sowie von IUnknown und IRpcProxyBuffer unterstützen.
Zu verschiedenen Zeiten müssen Proxys und Stubs Arbeitsspeicher zuweisen oder freigeben. Schnittstellenproxys müssen beispielsweise Arbeitsspeicher zuordnen, in dem Parameter an ihren Aufrufer zurückgegeben werden können. In dieser Hinsicht sind Schnittstellenproxys und Schnittstellen-Stubs nur normale COM-Komponenten, da sie die Standardtaskzuweisung verwenden sollten. (Siehe CoGetMalloc.)
Anforderungen
Anforderung | Wert |
---|---|
Unterstützte Mindestversion (Client) | Windows 2000 Professional [Desktop-Apps | UWP-Apps] |
Unterstützte Mindestversion (Server) | Windows 2000 Server [Desktop-Apps | UWP-Apps] |
Zielplattform | Windows |
Kopfzeile | objidl.h (include ObjIdl.h) |