| Feed: Monopoly Notes Titel: Studie Anmerkungen zu "COM -Prinzipien und Anwendungen" | Autor: FGS_FGS Kommentare |
| "COM -Prinzipien und Anwendungen" Studiennotizen - Teil 1 COM -Prinzipien http://savetime.delphibs.com Startzeit: 2004.1.30 Zuletzt geändert: 2004.2.1 Das Format dieses Artikels lautet: Der Text wird automatisch vom Fenster verpackt; (Der Inhalt dieses Artikels wird im Grunde genommen aus dem Buch "COM -Prinzipien und -Antretierungen" ausgewählt. Das Urheberrecht befindet sich dem Autor Pan Aimin. Bitte verwenden Sie ihn nicht in öffentlichen Medien.) Inhaltsverzeichnis ====================================================== ====================================================== ========== ⊙ Kapitel 1 Übersicht Was ist com COM -Objekte und Schnittstellen COM -Prozessmodell Com Wiederverwendbarkeit ⊙ Kapitel 2 COM -Objektmodell Global eindeutige Identifikator -Richtlinie Com -Objekt COM -Schnittstelle Schnittstellenbeschreibung Sprache IDL IUKNNOWN -Schnittstelle Schnittstellenprinzipien für COM -Objekte ⊙ Kapitel 3 Implementierung von com COM -Komponentenregistrierungsinformationen Registrieren Sie COM -Komponenten Klassenfabrik und DllgetObjectClass -Funktion CogetClassObject -Funktion Cocreateinstance / Cocreateinstanceex -Funktionen Initialisierung der COM -Bibliothek Speicherverwaltung der COM -Bibliothek Laden und Deinstallieren von Komponentenprogrammen Gemeinsame Funktionen für die COM -Bibliothek HRESULT -Typ ⊙ Kapitel 4 Com -Funktionen Wiederverwendbarkeit: Inklusion und Aggregation Prozesstransparenz (gelernt zu werden) Sicherheit (gelernt zu werden) Multithreading -Funktionen (zu lernen) ⊙ Kapitel 5 Entwickeln von COM -Anwendungen mit visueller C ++ Beschreibung einiger Header -Dateien von Win32 SDK bereitgestellt Einige Makros im Zusammenhang mit der COM -Schnittstelle ====================================================== ====================================================== ========== Text ====================================================== ====================================================== ========== ⊙ Kapitel 1 Übersicht ====================================================== ====================================================== ========== Was ist com -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- COM ist ein von Microsoft vorgeschlagener Komponentenstandard. Im COM-Standard wird ein Komponentenprogramm auch als Modul bezeichnet. Ein Komponentenprogramm kann ein oder mehrere Komponentenobjekte enthalten. ) ist ein Codeträger, der COM -Objekte bereitstellt. COM-Objekte unterscheiden sich von dem Objektkonzept in allgemeinen objektorientierten Sprachen (z. B. C ++). COM-Objekte sind sprachunabhängig. Diese Funktion kann mit Komponentenobjekten interagieren, die von verschiedenen Programmiersprachen entwickelt wurden. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- COM -Objekte und Schnittstellen -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Ähnlich wie das Konzept eines Objekts in C ++ ist ein Objekt eine Instanz einer Klasse; Eine Anwendung, die ein Objekt (oder ein anderes Objekt) verwendet, wird als Kunde bezeichnet, manchmal auch als Benutzer des Objekts bezeichnet. Eine Schnittstelle ist eine Reihe logisch verwandter Funktionen, und ihre Funktionen werden auch als Schnittstellenelementfunktionen bezeichnet. Laut Custom werden Schnittstellennamen häufig mit "I" vorangestellt. Objekte bieten Kunden über Schnittstellenfunktionen verschiedene Diensteformen. Im COM -Modell ist das Objekt selbst für den Kunden unsichtbar, und wenn der Kunden Service anfordert, kann es nur über die Schnittstelle durchgeführt werden. Jede Schnittstelle wird durch eine 128-Bit-global eindeutige Kennung (GUID) identifiziert. Der Client erhält den Schnittstellenzeiger über die GUID und übergibt dann den Schnittstellenzeiger, und der Client kann seine entsprechende Mitgliederfunktion aufrufen. Ähnlich wie bei Schnittstellen wird jede Komponente auch durch eine 128-Bit-GUID identifiziert, die als ClSID (Klassenkennung, Klassenkennung oder Klassen-ID) bezeichnet wird. Nachdem der Client das Objekt erfolgreich erstellt hat, erhält der COM -Objekt einen Zeiger auf eine Schnittstelle des Objekts. es alle Dienste. Gemäß der COM -Spezifikation kann eine andere Schnittstelle des Objekts von einer bestimmten Schnittstelle erhalten werden, wenn ein COM -Objekt mehrere Schnittstellen implementiert. Aus diesem Prozess können wir auch erkennen, dass der Client nur mit dem COM -Objekt über Schnittstellen handelt und das Objekt nur eine Reihe von Schnittstellen für den Client ist. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- COM -Prozessmodell -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Die von COM bereitgestellten Servicekomponentenobjekte haben beim Implementieren zwei Prozessmodelle: In-Process-Objekte und Out-of-Process-Objekte. Wenn es sich um ein In-Process-Objekt handelt, wird es im Client-Prozessraum ausgeführt. In-Process-Serviceprogramm: Das Serviceprogramm wird in den Prozess des Kunden geladen. Lokale Serviceprogramme: Das Serviceprogramm läuft auf demselben Computer wie das Client -Programm. Remote -Service -Programm: Das Serviceprogramm wird auf einem anderen Computer ausgeführt als der Client und kann entweder ein DLL -Modul oder eine EXE -Datei sein. Wenn das Remote -Service -Programm in DLL -Form implementiert ist, erstellt der Remote -Computer einen Proxy -Prozess. Obwohl COM -Objekte unterschiedliche Prozessmodelle haben, ist dieser Unterschied für Client -Programme transparent. Bei der Implementierung von COM -Objekten sollten Sie jedoch das Prozessmodell sorgfältig auswählen. Der Vorteil von In-Process-Modellen besteht darin, dass sie effizient sind, aber instabile Komponenten führen dazu, dass der Client-Prozess stürzt, so -OF-Process-Modell wird auch Probleme haben, was möglicherweise darin besteht Stabilität und der Komponentenprozess gefährden das Client-Programm nicht. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Com Wiederverwendbarkeit -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Da der COM-Standard auf Binärcode-Ebene basiert, unterscheidet sich die Wiederverwendbarkeit von COM-Objekten vom Wiederverwendungsprozess von Objekten in allgemeinen objektorientierten Sprachen wie C ++. Für das Client -Programm des COM -Objekts verwendet es nur die vom Objekt bereitgestellten Dienste über die Schnittstelle und kennt den Implementierungsprozess innerhalb des Objekts nicht. Anstelle der spezifischen Implementierung ist dies der Schlüssel zum Aufbau von Wiederverwendung. COM verwendet zwei Mechanismen, um die Wiederverwendung von Objekten zu verwirklichen. Wir gehen davon aus, dass es zwei COM -Objekte gibt, und Object 1 hofft, die Funktion des Objekts wiederzuverwenden. Wir nennen Objekt 1 ein externes Objekt und Objekt 2 ein internes Objekt. (1) integrativer Weg. Objekt 1 enthält Objekt 2. Wenn Objekt 1 die Funktion von Objekt 2 verwenden muss, kann es einfach die Implementierung an Objekt übergeben. Obwohl Objekt 1 und Objekt 2 dieselbe Schnittstelle unterstützen, ist Objekt 1 bei der Implementierung der Schnittstelle Die Implementierung von Objekt 2 wird aufgerufen. (2) Aggregationsmethode. Object 1 legt einfach die Schnittstelle von Objekt 2 dem Client ein. existieren. ====================================================== ====================================================== ========== ⊙ Kapitel 2 COM -Objektmodell ====================================================== ====================================================== ========== Global eindeutige Identifikator -Richtlinie -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Die COM-Spezifikation verwendet eine 128-Bit-GUID weltweit eindeutiger Bezeichner, um Objekte und Schnittstellen zu identifizieren, bei denen es sich um Zufallsnummern handelt und keine spezialisierten Agenturen zur Zuordnung und Verwaltung erfordern. Da GUID eine zufällige Zahl ist, ist die Einzigartigkeit nicht absolut garantiert, aber die Möglichkeit, dass die Identifikatoren verdoppelt werden, ist sehr gering. Wenn eine Maschine 100.000.000 Guids pro Sekunde erzeugt, kann man garantiert werden, dass 3240 Jahre (im Sinne der Wahrscheinlichkeit) nicht wiederholt werden. Die GUID kann in C/C ++ unter Verwendung dieser Struktur beschrieben werden: typedef struct _guid { DWORD DATA1; Wortdaten2; Wortdaten3; Byte Data4 [8]; } Guid; Beispiel: {64BF4372-1007-B0AA-444553540000} Sie können eine Richtlinie wie folgt definieren: EXTERN "C" const Guid clsid_myspellChecker = {0x54bf0093, 0x1048, 0x399d,, {0xb0, 0xa3, 0x45, 0x33, 0x43, 0x90, 0x47, 0x47}}; Visual C ++ enthält zwei Programme zum Generieren von Richtlinien: uUidgen.exe (Befehlszeile) und Guidgen.exe (Dialog). Die COM -Bibliothek enthält die folgenden API -Funktionen, mit denen GUIDs generiert werden können: Hresult cocreateguid (Guid *pGuid); Wenn die GUID erfolgreich erstellt wird, gibt die Funktion S_OK und PGUID -Punkte auf den resultierenden Richtwert zurück. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Com -Objekt -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- In der COM-Spezifikation sind COM-Objekte nicht streng definiert, aber COM bietet ein objektorientiertes Komponentenmodell, und COM-Komponenten bieten Kunden Entitäten, die in Objektform eingekapselt sind. Die Entität, in der das Client -Programm mit dem COM -Programm interagiert, ist ein COM -Objekt. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- COM -Schnittstelle -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Technisch gesehen ist eine Schnittstelle eine Datenstruktur, die eine Reihe von Funktionen enthält, über die Client -Code die Funktionen von Komponentenobjekten aufrufen kann. Die Schnittstelle definiert eine Reihe von Mitgliedsfunktionen, die alle Informationen von Komponentenobjekten enthüllen. Normalerweise rufen wir die Virtual Function Table (VTABLE) der Schnittstellenfunktionstabelle auf, und der Zeiger auf die VTABLE ist pvtable. Für eine Schnittstelle wird die virtuelle Funktionstabelle ermittelt, so In der Definition einer Schnittstelle müssen alle diese Informationen auf Binärebene ermittelt werden. Schnittstellenzeiger ----> Pvtable ----> Zeigerfunktion 1-> | ----------- | m_data1 Zeigerfunktion 2 -> | Objektimplementierung | m_data2 Zeigerfunktion 3-> | ------------ | Der erste Parameter jeder Schnittstellenelementfunktion ist ein Zeiger auf die Objektinstanz (= dies). In Informationen kann die Schnittstelle wissen, auf welchem COM -Objekt arbeitet. In Schnittstellenmitgliedern müssen String -Variablen Unicode -Zeichenzeiwerte verwenden. Wenn im Komponentenprogramm ANSI -Zeichen verwendet werden, sollten daher zwei Zeichenausdrücke konvertiert werden. Natürlich können Sie bei der Festlegung von Komponentenprogrammen und Client -Programmen die Parametertypen verwenden, die Sie selbst definieren, solange sie mit den Parametertypen kompatibel sind, die COM erkennen können. Visual C ++ bietet zwei String -Conversions: Namespace _com_util { BSTR CONVERTSTRINGTOBSTR (const char *psrc) throw (_com_error); BSTR CONVERTBSTRTOSTRING (BSTR PSRC) Throw (_com_error); } BSTR ist eine Doppel-Byte-Brennzeichenfolge, die der am häufigsten verwendete automatisierte Datentyp ist. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Schnittstellenbeschreibung Sprache IDL -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Die COM -Spezifikation verwendet die DCE -Spezifikation von OSF, um die Remote -Call -Schnittstelle (Schnittstellenbeschreibung Sprache) zu beschreiben und um die Beschreibungssprache der COM -Schnittstelle zu bilden. Schnittstellenbeschreibung Sprache bietet eine Beschreibungsmethode für Schnittstellen, die nicht von einer Sprache abhängen, sodass sie zu einer gemeinsamen Sprache zwischen Komponentenprogrammen und Client -Programmen werden kann. Die von der COM -Spezifikation verwendete IDL -Schnittstelle kann nicht nur die COM -Schnittstelle definieren, sondern auch einige häufig verwendete Datentypen und benutzerdefinierte Datenstrukturen definieren. . IDL unterstützt Zeigertypen, die C/C ++ sehr ähnlich sind. Zum Beispiel: Schnittstellen -Idictionary { HResult initialize () HResult Loadlibrary ([in] String); HResult InsertWord ([in] String, [in] String); HResult DeleteWord ([in] String); HResult Lookupword ([in] String, [out] String *); HResult restorelibrary ([in] String); Hresult freelibrary (); } Microsoft Visual C ++ bietet MIDL-Tools, mit denen IDL-Schnittstellenbeschreibungsdateien in C/C ++-kompatible Schnittstellenbeschreibung Header-Header-Dateien (.H) kompiliert werden können. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- IUKNNOWN -Schnittstelle -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Iunknowns IDL -Definition: Schnittstelle IUKNNOWN { HResult queryInterface ([in] refiid iid, [out] void ** ppv); Ulong addref (void); Ulong -Freisetzung (void); } Iunkowns C ++ - Definition: Klasse IUKNNOWN { virus hResult _stdcall queryInterface (const iid & iid, void ** ppv) = 0; virtual Ulong _stdcall addRef () = 0; virus ulong _stdcall release () = 0; } -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Schnittstellenprinzipien für COM -Objekte -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Die COM -Spezifikation legt die folgenden Regeln für die Funktion queryInterface fest: 1. Für verschiedene Schnittstellenzeiger desselben Objekts muss die durch Abfrage erhaltene Schnittstelle genau gleich sein. Das heißt, der Zeiger der IunkNown -Schnittstelle für jedes Objekt ist einzigartig. Daher können wir für zwei Schnittstellenzeiger feststellen, ob sie auf dasselbe Objekt verweisen, indem wir beurteilen, ob die von ihnen abfragen von IUKNNOWN -Schnittstellen gleich sind. 2. Schnittstellenreflexivität. Das Abfragen einer Schnittstelle selbst sollte beispielsweise immer erfolgreich sein: Pidictionary-> QueryInterface (Iid_Dictionary, ...) sollte S_OK zurückgeben. 3. Schnittstellensymmetrie. Wenn Sie von einem Schnittstellenzeiger auf einen anderen Schnittstellenzeiger abfragen, muss der Rückkehr vom zweiten Schnittstellenzeiger zum ersten Schnittstellenzeiger zum Beispiel erfolgreich sein: Pidictionary-> queryInterface (iid_spellcheck, (void **) & pispellcheck); Wenn die Suche erfolgreich ist, wird die Iid_Dictionary -Schnittstelle von Pispellcheck auf jeden Fall erfolgreich sein. 4. Schnittstellentransitivität. Wenn Sie den zweiten Schnittstellenzeiger aus dem ersten Schnittstellenzeiger abfragen und der dritte Schnittstellenzeiger aus dem zweiten Schnittstellenzeiger abfragt werden, können Sie definitiv den ersten Schnittstellenzeiger aus dem dritten Schnittstellenzeiger abfragen. 5. Schnittstellenabfragezeit irrelevant. Wenn ein bestimmter Schnittstellenzeiger in einem bestimmten Zeitpunkt gefunden werden kann, wird der gleiche Schnittstellenzeiger jederzeit in der Zukunft überprüft, und die Abfrage wird definitiv erfolgreich sein. Kurz gesagt, unabhängig davon, an welcher Schnittstelle wir beginnen, können wir immer jede Schnittstelle erreichen und können immer zur ursprünglichen Schnittstelle zurückkehren. ====================================================== ====================================================== ========== ⊙ Kapitel 3 Implementierung von com ====================================================== ====================================================== ========== COM -Komponentenregistrierungsinformationen -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Informationen zu allen Komponenten auf dem aktuellen Computer HKEY_CLASS_ROOT/CLSID In-Process-Komponente HKEY_CLASS_ROOT/CLSID/GUID/INPROCSERVER32 Out-of-Process-Komponente HKEY_CLASS_ROOT/CLSID/GUID/LOCALERVER32 Kategorie, in der Komponente (CATID) hkey_class_root/clsid/rid/implementierte Kategorien COM -Schnittstellenkonfigurationsinformationen hkey_class_root/interface Proxy Dll/Stub DLL HKEY_CLASS_ROOT/CLSID/GUID/Proxystubclsid HKEY_CLASS_ROOT/CLSID/GUID/Proxystubclsid32 Informationen zum Typ Bibliothek HKEY_CLASS_ROOT/TYPELIB String naming progid hkey_class_root/ (z. B. "comctl.treectrl") Komponentenrichtlinie hkey_class_root/comtrl.treecontrol/clsid Standardversionsnummer hkey_class_root/comtrl.treecontrol/curver (z. B. curver = "comtrl.treectrl.1", dann Hkey_class_root/comtrl.treecontrol.1 existiert auch) Alle Komponentenkategorien der aktuellen Maschine HKEY_CLASS_ROOT/COMPONENT CATEGOREN COM bietet zwei API -Funktionen clsidfromprogid und progidfromclsid, um Progid und CLSID umzuwandeln. Wenn die COM -Komponente den gleichen Satz von Schnittstellen unterstützt, können sie in dieselbe Klasse eingeteilt werden und eine Komponente kann in mehrere Klassen eingeteilt werden. Wenn beispielsweise alle Automatisierungsobjekte die IDispatch -Schnittstelle unterstützen, können sie als "Automatisierungsobjekte" klassifiziert werden. Kategorieinformationen werden auch von einem GUID bezeichnet, der als Katid bezeichnet wird. Der Hauptzweck von Komponentenkategorien ist, dass Kunden schnell bestimmte Arten von Komponentenobjekten auf der Maschine ermitteln können. Die Schnittstelle, die jetzt Komponentenkategorien verwendet, kann den Abfrageprozess speichern. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Registrieren Sie COM -Komponenten -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- REGSRV32.EXE wird verwendet, um eine In-Process-Komponente zu registrieren, die die Dllregiererver- und Dllunregiererver-Funktionen der DLL aufruft, um die Registrierung und Stornierung des Komponentenprogramms zu vervollständigen. Wenn die Operation erfolgreich ist, geben Sie true zurück, andernfalls geben Sie false zurück. Für außerhalb der Prozesskomponentenprogramme ist die Situation etwas anders, da es sich selbst um ein ausführbares Programm handelt und keine Einstiegsfunktionen für andere Programme bereitstellen kann. Daher sieht die COM-Spezifikation vor, dass sich außerhalb der Prozesskomponenten, die die Selbstregistrierung unterstützen, zwei Befehlszeilenparameter /RegServer und /unregServer unterstützen müssen, um die Registrierungs- und Stornierungsvorgänge abzuschließen. Befehlszeilenparameter sind fälschlich abhängig und "/" können durch "-" ersetzt werden. Wenn der Vorgang erfolgreich ist, gibt das Programm 0 zurück, da die Rückgabe von Nicht-0-Ausfällen ansonsten zurückgibt. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Klassenfabrik und DllgetObjectClass -Funktion -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Klassenfabrik ist die Produktionsbasis von COM -Objekten. Die Klassenfabrik selbst ist auch ein COM -Objekt, das eine spezielle Schnittstelle iCLASSFACTORY unterstützt: Klasse ICLASSFACTORY: Öffentlich iunkNOWN { Virtual Hresult _stdcall CreateInstance (IUKNNOWN *PUNKNOWNOUTER, const iid & iid, void ** ppv) = 0; virtual hResult _stdcall sperrerver (bool block) = 0; } Die Funktion createInstance -Mitgliedsfunktion wird verwendet, um das entsprechende COM -Objekt zu erstellen. Der erste Parameter -Punknownouter wird für den Fall verwendet, in dem die Objektklasse aggregiert ist, und wird im Allgemeinen auf Null eingestellt. Schnittstellenzeiger. Die Funktionen für Schlosservermember werden verwendet, um die Lebensdauer einer Komponente zu steuern. Das Klassenfabrikobjekt wird von der DLL-abgeleiteten Funktion DLLGetClassObject erstellt: HResult dllgetClassObject (const Clsid & clsid, const iid & iid, (void **) ppv); Der erste Parameter der DllGetClassObject -Funktion ist die CLSID des zu erstellenden Objekts. Da eine Komponente mehrere COM -Objektklassen implementieren kann, muss das CLSID in den Parametern der DllGetClassObject -Funktion angegeben werden, um die richtige Klassenfabrik zu erstellen. Die beiden anderen Parameter IID und PPV beziehen sich auf den angegebenen Schnittstellen -IID bzw. den Zeiger der Speicherklasse Factory Interface. Nachdem die Anweisung zum Erstellen eines Objekts empfangen wurde, ruft die COM -Bibliothek die Funktion dllGetClassObject der Komponente im Prozess auf, erstellt das Klassenfabrikobjekt aus der Funktion und gibt den Schnittstellenzeiger des Klassenfabrikobjekts zurück. Sobald eine COM -Bibliothek oder ein Kunde einen Schnittstellenzeiger auf die Klassenfabrik hat, können sie das entsprechende COM -Objekt über die Mitgliedsfunktion erstellen, die die ICLASSFACTORY erstellt. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- CogetClassObject -Funktion -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- In der COM -Bibliothek gibt es drei APIs, die für die Erstellung von Objekten verwendet werden können, nämlich CogetClassObject, Cocreateinstnace und Cocreateinstanceex. In der Regel ruft das Client -Programm eine davon auf, um die Erstellung des Objekts zu vervollständigen und den anfänglichen Schnittstellenzeiger des Objekts zurückzugeben. Die COM -Bibliothek und die Klassenfabrik interagieren auch diese drei Funktionen. Hresult CogetClassObject (const Clsid & ClSID, DWORD DWCLSCONTEXT, COSERVERINFO *PSERVERINFO, const iid & iid, (void **) ppv); Die CogetClassObject -Funktion findet zunächst die Klassenfabrik der von CLSID angegebenen COM -Klasse und wird bei Bedarf eine Verbindung zum Klassenfabrik -Objekt hergestellt. Wenn es sich um ein In-Process-Komponentenobjekt handelt, ruft CogetClassObject das DllGetClassObject des DLL-Moduls auf, um die Funktion einzuführen, die Parameter CLSID, IID und PPV an die Funktion dllGetClassObject zu übergeben und gibt den Schnittstellenzeiger des Klassenfabrikobjekts zurück. Normalerweise ist IID die Kennung iid_iclassFactory von iclassFactory. Wenn das Klassenfabrikobjekt auch andere Schnittstellen unterstützt, die zum Erstellen von Operationen verwendet werden können, können auch andere Schnittstellenkennungen verwendet werden. Beispielsweise kann die ICLASSFactory2 -Schnittstelle angefordert werden, um den Lizenzstatus des Benutzers zum Erstellungszeit zu überprüfen. Die ICLASSFactory2 -Schnittstelle ist eine Erweiterung auf iCLASSFactory, die die Sicherheit der Komponentenerstellung verbessert. Der Parameter DWClsContext gibt die Komponentenkategorie an, die als In-Process-Komponente, als Out-of-Process-Komponente oder als In-Process-Steuerobjekt angegeben werden kann in der OLE -Technologie). Die Parameter IID und PPV entsprechen den Parametern von dllgetClassObjec und werden verwendet, um die Schnittstelle IID und den Schnittstellenzeiger für das Speichern des Klassenobjekts anzugeben. Mit dem Parameter-PSERVERINFO werden beim Erstellen von Remote-Objekten Serverinformationen angegeben. Die Situation ist viel komplizierter, wenn sich das von der CogetClassObject-Funktion erstellte Klassenfabrik-Objekt in einer außerfeilenden Komponente befindet. Zunächst startet die CogetClassObject -Funktion den Komponentenprozess und wartet dann, bis der Komponentenprozess die Klassenfabrik des COM -Klasse -Objekts registriert, das sie unterstützt. Die CogetClassObject -Funktion gibt also die entsprechenden Klassenfabrikinformationen in COM zurück. Wenn ein Prozess außerhalb der Komponenten von der COM-Bibliothek gestartet wird (mit dem Befehlszeilenparameter "/Einbettung"), muss er die unterstützten Fabrikobjekte der COM-Klasse über die Funktion coregisterClassObject registrieren, damit die COM-Bibliothek die COM-Bibliothek kann Erstellen Sie COM -Objekte zur Verwendung. Wenn der Prozess beendet ist, muss die Funktion corevokeClassObject aufgerufen werden, um Com darüber zu informieren, dass das von ihm registrierte Klassenfabrikobjekt nicht mehr gültig ist. Das Komponentenprogramm ruft die Funktion coregisterClassObject auf und die CoreVokeClassObject -Funktion muss gepaart werden, um die Konsistenz der COM -Informationen sicherzustellen. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Cocreateinstance / Cocreateinstanceex -Funktionen -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Hresult Cocreateinstance (const Clsid & Clsid, iUkNNOWN *PunkNOWNOUTER, DWORD DWCLSCONTEXT, const iid & iid, (void **) ppv); Cocrreateinstance ist eine verpackte Helferfunktion, die die CogetClassObject -Funktion darin aufruft. The meaning of the parameters clsid and dwClsContext of CoCreateInstance are consistent with the corresponding parameters of CoGetClassObject (the iid and ppv parameters of CoCreateInstance are different from CoGetClassObject, one is the interface information representing the object, and the other is the interface information representing the class Fabrik). Der Parameter -Punknownouter stimmt mit den entsprechenden Parametern in der Erstellung der Klassenfabrik -Schnittstelle überein und wird hauptsächlich in dem Fall verwendet, in dem Objekte aggregiert sind. Die Cocrreateinstance -Funktion enthält den Prozess des Erstellens von Objekten über eine Klassenfabrik. Cocrreateinstance kann mit dem folgenden Code implementiert werden: (Savetime Hinweis: Die Anwendung des PPV -Zeigers im folgenden Code scheint ungültig zu sein **) Hresult Cocreateinstance (const Clsid & Clsid, iUkNNOWN *PunkNOWNOUTER, DWORD DWCLSCONTEXT, const iid & iid, void *ppv) { ICLASSFACTORY *PCF; Hresult HR; hr = cogetClassObject (CLSID, dwclscontext, null, iid_iclassfactory, (void *) pcf); if (fehlgeschlagen (hr)) return hr; hr = pcf-> createInstance (punknownouter, iid, (void *) ppv); PFC-> Release (); Rückkehr HR; } Aus diesem Code können wir sehen, dass die Cocreateinstance -Funktion zuerst die CogetClassObject -Funktion verwendet, um ein Klassenfabrikobjekt zu erstellen, und dann den Schnittstellenzeiger des Class Factory -Objekts zum Erstellen eines realen COM -Objekts verwendet. Zurückgegeben, so dass die Klasse in Gebrauch gebracht wird. Die Verwendung von Cocrreateinstance erstellt jedoch kein Objekt auf der Remote -Maschine, da beim Aufrufen von CogetClassObject der dritte Parameter zum Angeben der Serverinformationen auf null festgelegt wird. Wenn Sie ein Remote -Objekt erstellen möchten, können Sie Cocrreateinstance's Extension Function CocrreateinstanceEx verwenden: Hresult cocreateinstanceex (const Clsid & Clsid, iUkNNOWN *PunkNOWNOUTER, DWORD DWCLSCONTEXT, COSERVERINFO *PSERVERINFO, DWORD DWCOUNT, Multi_qi *rgmultiqi); Die ersten drei Parameter sind mit Cocrreateinstance die gleichen. Schnittstellenzeiger. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Initialisierung der COM -Bibliothek -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Bevor Sie die Funktionen der Com -Bibliothek aufrufen, muss die Initialisierungsfunktion der COM -Bibliothek aufgerufen werden, um die Funktion gültig zu machen: HResult coinitialize (imalloc *pmalloc); PMALLOC wird verwendet, um einen Speicherallocator anzugeben, und das Speicherzuweisungsprinzip kann von der Anwendung angegeben werden. Wenn wir den Parameter direkt auf NULL festlegen, verwendet die COM -Bibliothek im Allgemeinen den Standard -Speicher -Allocator. Rückgabewert: S_OK bedeutet, dass die Initialisierung erfolgreich ist S_FALSE zeigt an, dass die Initialisierung erfolgreich ist, aber dieser Aufruf ist nicht das erste Mal, dass die Initialisierungsfunktion in diesem Prozess aufgerufen wird. S_unexpected zeigt an, dass während des Initialisierungsprozesses ein Fehler aufgetreten ist und die Anwendung die COM -Bibliothek nicht verwenden kann. Normalerweise initialisiert ein Prozess die COM -Bibliothek nur einmal und es ist nicht sinnvoll, die COM -Bibliothek mehrmals in derselben Moduleinheit zu initialisieren. Die einzige Funktion, die die COM -Bibliothek nicht initialisieren muss, besteht darin, die COM -Bibliotheksversion zu erhalten: DWORD COBUILDVERSION (); Rückgabewert: High 16-Bit Major Versionsnummer Untere 16 -stellige Versionsnummer Nachdem das COM -Programm den COM -Bibliotheksdienst verbraucht hat, in der Regel vor dem Ablauf des Programms, müssen Sie die beendete COM -Bibliotheksdienstfunktion anrufen, um die von der COM -Bibliothek verwalteten Ressourcen zu befreien: void Couninitialize (void); Hinweis: Jedes Prozess- oder Programmmodul, der die Coinitialize -Funktion aufruft und S_OK zurückgibt, muss über einen entsprechenden beratendischen Funktionsaufruf verfügen, um sicherzustellen, dass die COM -Bibliothek effektiv Ressourcen verwendet. . -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Speicherverwaltung der COM -Bibliothek -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Da COM-Komponentenprogramme und Client-Programme durch Standards auf binärer Ebene verbunden sind, müssen alle Vorgänge, die Speicherinteraktionen zwischen Clients, COM-Bibliotheken und -komponenten (Zuordnung und Freigabe nicht im selben Modul) in COM-Anwendungen enthalten. Der von COM bereitgestellte Speicherverwaltungsstandard ist eigentlich eine Imalloc -Schnittstelle: // iid_imalloc: {00000002-0000-0000-c000-0000000046} Klasse imalloc: öffentlich iunkNOown { void * alloc (ulong cb) = 0; void * realloc (void * pv, ulong cb) = 0; void Free (void *pv) = 0; Ulong GetSize (void *pv) = 0; int dayalloc (void *pv) = 0; void heapminimize () = 0; // Betriebssystem für die Leistungsoptimierung } Erhalten Sie den Zeiger der IMALC -Schnittstelle: HResult cogetmalloc (DWORD DWMEMCONTEXT, IMALLOC ** PPMALLOC); Der erste Parameter der CogetMalloc -Funktion DWMemContext wird verwendet, um den Typ des Speichermanagers anzugeben. Die COM -Bibliothek enthält zwei Speichermanager, einer der während der Initialisierung angegebene Speichermanager oder dessen interner Standard -Manager, auch als Job Manager (Aufgabe -Allocator) bekannt. Memctx_task im DWMemContext-Parameter; Prozess und an einen zweiten Prozess übergeben, diesen Speicher im zweiten Prozess verwendet oder sogar freigegeben. Solange der Rückgabewert der Funktion S_OK ist, verweist PPMALLOC auf den Zeiger der Memory Manager -Schnittstelle der COM -Bibliothek, und Sie können sie nach der Verwendung von Speichervorgängen ausführen. Die COM -Bibliothek fasst drei API -Funktionen zusammen, die für die Speicherzuweisung und die Veröffentlichung verwendet werden können: void * cotaskmemalloc (ulong cb); void cotaskfree (void *pv); void cotaskmemrealloc (void *pv, ulong cb); Diese drei Funktionen werden drei Mitgliedsfunktionen zugeordnet, die IMALloc entsprechen: Alloc, Realloc und Free. Beispiel: Wie ein COM -Programm den entsprechenden progiden Wert aus dem CLSID -Wert findet: Wchar *pwprogid; char pszprogid [128]; hResult = :: progidfromclsid (ClSID_Dictionary, & pwProgid); if (hResult! = s_ok) { ... } WCSTOMBS (PSZPROGID, PWPROGID, 128); CotaskMemfree (PWPROGID); Nach dem Aufrufen der COM -Funktion progidfromclsid zur Rückgabe, da die COM -Bibliothek den Speicherplatz für die Ausgabebehunde PWProgid zuteilt, muss die Anwendung die CotaskMemfree -Funktion aufrufen, um den Speicher nach der Verwendung der PWProgid -Variablen zu freien. Dieses Beispiel zeigt eine Situation, in der das Speicher in der COM -Bibliothek zugewiesen wird und der Speicher im Anrufprogramm freigegeben wird. Einige andere Funktionen in der COM -Bibliothek weisen ebenfalls ähnliche Eigenschaften auf, insbesondere einige Funktionen, die eine unbestimmte Länge -Ausgangsparameter enthalten. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Laden und Deinstallieren von Komponentenprogrammen -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Laden von Komponenten in Bearbeitung: 客户程序调用COM 库的CoCreateInstance 或CoGetClassObject 函数创建COM 对象,在CoGetClassObject 函数中,COM 库根据系统注册表中的信息,找到类标识符CLSID 对应的组件程序(DLL 文件)的全路径,然后调用LoadLibrary(实际上是CoLoadLibrary)函数,并调用组件程序的DllGetClassObject 引出函数。DllGetClassObject 函数创建相应的类厂对象,并返回类厂对象的IClassFactory 接口。至此CoGetClassObject 函数的任务完成,然后客户程序或者CoCreateInstance 函数继续调用类厂对象的CreateInstance 成员函数,由它负责COM 对象的创建工作。 CoCreateInstance |-CoGetClassObject |-Get CLSID -> DLLfile path |-CoLoadLibrary |-DLLfile.DllGetClassObject |-return IClassFactory |-IClassFactory.CreateInstnace 进程外组件的装载: 在COM 库的CoGetClassObject 函数中,当它发现组件程序是EXE 文件(由注册表组件对象信息中的LocalServer 或LocalServer32 值指定)时,COM 库创建一个进程启动组件程序,并带上“/Embedding”命令行参数,然后等待组件程序;而组件程序在启动后,当它检查到“/Embedding”命令行参数后,就会创建类厂对象,然后调用CoRegisterClassObject 函数把类厂对象注册到COM 中。当COM 库检查到组件对象的类厂之后,CoGetClassObject 函数就把类厂对象返回。由于类厂与客户程序运行在不同的进程中,所以客户程序得到的是类厂的代理对象。一旦客户程序或COM 库得到了类厂对象,它就可以完成组件对象的创建工作。 进程内对象和进程外对象的不同创建过程仅仅影响了CoGetClassObject 函数的实现过程,对于客户程序来说是完全透明的。 CoGetClassObject |-LocalServer/LocalServer32 |-Execute EXE /Embedding |-Create class factory |-CoRegisterClassObject ( class factory ) |-return class factory (proxy) 进程内组件的卸载: 只有当组件程序满足了两个条件时,它才能被卸载,这两个条件是:组件中对象数为0,类厂的锁计数为0。满足这两个条件时,DllCanUnloadNow 引出函数返回TRUE。COM 提供了一个函数CoFreeUnusedLibraries,它会检测当前进程中的所有组件程序,当发现某个组件程序的DllCanUnloadNow 函数返回TRUE 时,就调用FreeLibrary 函数(实际上是CoFreeLibrary 函数)把该组件从程序从内存中卸出。 该由谁来调用CoFreeUnusedLibraries 函数呢?因为在组件程序执行过程中,它不可能把自己从内存中卸出,所以这个任务应该由客户来完成。客户程序随时都可以调用CoFreeUnusedLibraries 函数完成卸出工作,但通常的做法是,在程序的空闲处理过程中调用CoFreeUnusedLibraries 函数,这样做既可以避免程序中处处考虑对CoFreeUnusedLibraries 函数的调用,又可以使不再使用的组件程序得到及时清除,提高资源的利用率,COM 规范也推荐这种做法。 进程外组件的卸载: 进程外组件的卸载比较简单,因为组件程序运行在单独的进程中,一旦其退出的条件满足,它只要从进程的主控函数返回即可。在Windows 系统中,进程的主控函数为WinMain。 前面曾经说过,在组件程序启动运行时,它调用CoRegisterClassObject 函数,把类厂对象注册到COM 中,注册之后,类厂对象的引用计数始终大于0,因此单凭类厂对象的引用计数无法控制进程的生存期,这也是引入类厂对象的加锁和减锁操作的原因。进程外组件的载条件与DllCanUnloadNow 中的判断类似,也需要判断COM 对象是否还存在、以及判断是否锁计数器为0,只有当条件满足了,进程的主函数才可以退出。 从原则上讲,进程外组件程序的卸载就是这么简单,但实际上情况可能复杂一些,因为有些组件程序在运行过程中可以创建自己的对象,或者包含用户界面的程序在运行过程中,用户手工关闭了进程,那么进程对这些动作的处理要复杂一些。例如,组件程序在运行过程中,用户又打开了一个文件并进行操作,那么即使原先创建的对象被释放了,而且锁计数器也为0,进程也不能退出,它必须继续为用户服务,就像是用户打开的进程一样。对这种程序,可以增加一个“用户控制”标记flag,如果flag 为FALSE,则可以按简单的方法直接退出程序即可;如果flag 为TRUE,则表明用户参与了控制,组件进程不能马上退出,但应该调用CoRevokeClassObject 函数以便与CoRegisterClassObject 调用相响呼应,把进程留给用户继续进行。 如果组件程序在运行过程中,用户要关闭进程,而此时并不满足进程退出条件,那么进程可以采取两种办法:第一种方法,把应用隐藏起来,并把flag 标记设置为FALSE,然后组件程序继续运行直到卸载条件满足为止;另一种办法是,调用CoDisconnectObject 函数,强迫脱离对象与客户之间的关系,并强行终止进程,这种方法比较粗暴,不提倡采用,但不得已时可以也使用,以保证系统完成一些高优先级的操作。 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- COM 库常用函数 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- 初始化函数CoBuildVersion 获得COM 库的版本号 CoInitialize COM 库初始化 CoUninitialize COM 库功能服务终止 CoFreeUnusedLibraries 释放进程中所有不再使用的组件程序 GUID 相关函数IsEqualGUID 判断两个GUID 是否相等 IsEqualIID 判断两个IID 是否相等 IsEqualCLSID 判断两个CLSID 是否相等(*为什么要3个函数) CLSIDFromProgID 字符串组件标识转换为CLSID 形式 StringFromCLSID CLSID 形式标识转化为字符串形式 IIDFromString 字符串转换为IID 形式 StringFromIID IID 形式转换为字符串 StringFromGUID2 GUID 形式转换为字符串(*为什么有2) 对象创建函数CoGetClassObject 获取类厂对象 CoCreateInstance 创建COM 对象 CoCreateInstanceEx 创建COM 对象,可指定多个接口或远程对象 CoRegisterClassObject 登记一个对象,使其它应用程序可以连接到它 CoRevokeClassObject 取消对象的登记 CoDisconnectObject 断开其它应用与对象的连接 内存管理函数CoTaskMemAlloc 内存分配函数 CoTaskMemRealloc 内存重新分配函数 CoTaskMemFree 内存释放函数 CoGetMalloc 获取COM 库内存管理器接口 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- HRESULT 类型 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- 大多数COM 函数以及一些接口成员函数的返回值类型均为HRESULT 类型。HRESULT 类型的返回值反映了函数中的一些情况,其类型定义规范如下: 31 30 29 28 16 15 0 |-----|--|------------------------|-----------------------------------| 类别码(30-31) 反映函数调用结果: 00 调用成功 01 包含一些信息 10 警告 11 错误 自定义标记(29) 反映结果是否为自定义标识,1 为是,0 则不是; 操作码(16-28) 标识结果操作来源,在Windows 平台上,其定义如下: #define FACILITY_WINDOWS 8 #define FACILITY_STORAGE 3 #define FACILITY_RPC 1 #define FACILITY_SSPI 9 #define FACILITY_WIN32 7 #define FACILITY_CONTROL 10 #define FACILITY_NULL 0 #define FACILITY_INTERNET 12 #define FACILITY_ITF 4 #define FACILITY_DISPATCH 2 #define FACILITY_CERT 11 操作结果码(0-15) 反映操作的状态,WinError.h 定义了Win32 函数所有可能返回结果。 以下是一些经常用到的返回值和宏定义: S_OK 函数执行成功,其值为0 (注意,其值与TRUE 相反) S_FALSE 函数执行成功,其值为1 S_FAIL 函数执行失败,失败原因不确定 E_OUTOFMEMORY 函数执行失败,失败原因为内存分配不成功 E_NOTIMPL 函数执行失败,成员函数没有被实现 E_NOTINTERFACE 函数执行失败,组件没有实现指定的接口 不能简单地把返回值与S_OK 和S_FALSE 比较,而要用SECCEEDED 和FAILED 宏进行判断。 ====================================================== ====================================================== ========== ⊙ 第四章COM 特性 ====================================================== ====================================================== ========== 可重用性:包容和聚合 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- 包容模型: 组件对象在接口的实现代码中执行自身创建的另一个组件对象的接口函数(客户/服务器模型)。这个对象同时实现了两个(或更多)接口的代码。 聚合模型: 组件对象在接口的查询代码中把接口传递给自已创建的另一个对象的接口查询函数,而不实现该接口的代码。另一个对象必须实现聚合模型(也就是说,它知道自己正在被另一个组件对象聚合),以便QueryInterface 函数能够正常运作。 在组件对象被聚合的情况下,当客户请求它所不支持的接口或者请求IUnknown 接口时,它必须把控制交给外部对象,由外部对象决定客户程序的请求结果。 聚合模型体现了组件软件真正意义上的重用。 聚合模型实现的关键在CoCreateInstance 函数和IClassFactory 接口: HRESULT CoCreateInstance(const CLSID& clsid, IUnknown *pUnknownOuter, DWORD dwClsContext, const IID& iid, (void **)ppv); // class IClassFactory : public IUnknown virtual HRESULT _stdcall CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv) = 0; 其中pUnknownOuter 参数用于指定组件对象是否被聚合。如果pUnknownOuter 参数为NULL,说明组件对象正常使用,否则说明被聚合使用,pUnknownOuter 是外部组件对象的接口指针。 聚合模型下的被聚合对象的引用计数成员函数也要进行特别处理。在未被聚合的情况下,可以使用一般的引用计数方法。在被聚合时,由客户调用AddRef/Release 函数时,必须转向外部组件对象的AddRef/Release 方法。这时,外部组件对象要控制被聚合的对象必须采用其它的引用计数接口。 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- 进程透明性(待学) 安全性(待学) 多线程特性(待学) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- ====================================================== ====================================================== ========== ⊙ 第五章用Visual C++ 开发COM 应用 ====================================================== ====================================================== ========== Win32 SDK 提供的一些头文件的说明 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Unknwn.h 标准接口IUnknown 和IClassFacatory 的IID 及接口成员函数的定义 Wtypes.h 包含COM 使用的数据结构的说明 Objidl.h 所有标准接口的定义,即可用于C 语言风格的定义,也可用于C++ 语言 Comdef.h 所有标准接口以及COM 和OLE 内部对象的CLSID ObjBase.h 所有的COM API 函数的说明 Ole2.h 所有经过封装的OLE 辅助函数 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- 与COM 接口有关的一些宏 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- DECLARE_INTERFACE(iface) 声明接口iface,它不从其他的接口派生 DECLARE_INTERFACE_(iface, baseiface) 声明接口iface,它从接口baseiface 派生 STDMETHOD(method) 声明接口成员函数method,函数返回类型为HRESULT STDMETHOD_(type, method) 声明接口成员函数method,函数返回类型为type ====================================================== ====================================================== ========== ⊙ 结束 ====================================================== ====================================================== ========== |