Component Object Model Verständnis???
-
Hallo Leute,
bin seit kurzen dabei mich ich in C++ und DirectX einzulesen bzw. einzuarbeiten.
Nun bin ich aber an einen Punkt angekommen wo ich etwas am verzweifeln bin und zwar das Verständnis für der/die COM.Was hat das mit den Interfaces auf sich..und ..und . Es wäre nett wenn jemand dabei ein wenig unter die Arme greift?
Danke
Tom79
-
COM Interfaces sind im Prinzip sowas wie Klassen. Der Vorteil ist, dass man sie in vielen verschiedenen Sprachen benutzen kann. zB Pascal, Basic, C++, ka was sonst noch.
-
Was verstehst Du denn nicht?!?!
-
Mhhh..was ich nicht verstehe ist...
1. Was ist ein COM?
2. Wie baut sich ein COM auf ?
3. Wofür brauche ich COM und die Interfaces?
4. In welchem Bezug steht COM mit DirectX?Ich hoffe das sind konkrete Fragen!
Danke an alle die mir helfen!!!
Tom79
-
Original erstellt von 0x00000001:
COM Interfaces sind im Prinzip sowas wie Klassen. Der Vorteil ist, dass man sie in vielen verschiedenen Sprachen benutzen kann. zB Pascal, Basic, C++, ka was sonst noch.Hm, machen doch DLl's auch oder nicht ? Dann wäre doch COM umsonst ?
Cu
-
Kauf dir'n Buch darüber
-
Original erstellt von Tom79:
**Mhhh..was ich nicht verstehe ist...3. Wofür brauche ich COM und die Interfaces?
4. In welchem Bezug steht COM mit DirectX?Ich hoffe das sind konkrete Fragen!
Danke an alle die mir helfen!!!
Tom79**
3. ein mit COM aufgebautes Projekt lässt sich leicht verändern/verbessern/erweitern
4. dx ist auf COM aufgebaut
-
**Mhhh..was ich nicht verstehe ist...
1. Was ist ein COM?
2. Wie baut sich ein COM auf?
3. Wofür brauche ich COM und die Interfaces?
4. In welchem Bezug steht COM mit DirectX?Ich hoffe das sind konkrete Fragen!**
- 1. COM steht für Component Object Model - d.h. ein "Modell" (a.k.a. Konzept) für komponentenbasierte "Objekte" (Objekte muß hier nicht unbedingt als Instanz einer Klasse angesehen werden).
Es ist prinzipiell eine Erweiterung des Ansatzes der Objektorientierung, quasi "strikter".
Du kannst Dir ein Programm vorstellen, daß aus vielen verschiedenen Klassen (und zur Laufzeit später Objekten) besteht: Jedes Objekt kommuniziert über irgendwelche Methoden mit den anderen Objekten. Schön.
Jetzt soll aber ein Objekt geändert (umprogrammiert) werden, weil z.B. die Zeichen-Methode alles andere als effizient ist:
Das Objekt GrafikDevice hat z.B. die Methode:
public zeichneLinie(int pixelindex_x, int pixelindex_y) { // bla }
Solange diese Methode nur "intern" (also da wo das "// bla" ist) geändert wird (effizienter gemacht -> besserer Algorithmus z.B.) ist alles schön und gut:
Die ganzen anderen Klassen brauchen nicht geändert zu werden. Alles funktioniert trotzdem 1a.
Das ist ja das schöne an der OOP.Soa, jetzt fällt den Leuten aber ein, daß meinetwegen die Liniendicke mit angegeben werden sollte, um unterschiedlich dicke Linien direkt zu ermöglichen.
Es entsteht also:
public zeichneLinie(int pixelindex_x, int pixelindex_y, int liniendicke) { // bla }
Für besseres Verständnis lassen wir jetzt mal die Möglichkeit der "Überladung" weg.
Die Klasse GrafikDevice kann weiterhin kompiliert werden.
Aber alle anderen Klassen, die die Methode zeichneLinie() von GrafikDevice aufrufen, müssen auch umgeschrieben werden, sonst funzt nix mehr...Womit wir jetzt zusätzlich Deinen Punkt
- 2. hinzunehmen:
Nicht so bei COM: Durch COM werden die unterschiedlichen Klassen (Objekte) jetzt zu "echten" Komponenten, ich kann mir also aus verschiedenen Objekten ein Gesamtwerk "komponieren", wie ich lustig bin, ohne Angst, falls GrafikDevice wieder umgeschrieben wird, daß dann nix mehr läuft.
COM sind quasi die Legosteine des Programmierens: Ich kann sie zusammenbauen wie ich will! Selbst die neuesten Legosteine "Mindstorms" (or whatever) haben immer noch diese lustigen runden Pins, über die ich verschiedene Legosteine zusammenbauen kann.
Diese Pins wären bei COM die Interfaces.
Also "Schnittstellen", denn genau das sind sie!Um dieses Konzept für unser Beispiel umzusetzen, würde ich mir für GrafikDevice ein Interface basteln:
Dieses hat die Methode zeichneLinie(int, int).
Über das Interface "hol'" ich mir also nachher das eigentliche Objekt GrafikDevice, und benutze zeichneLinie(143, 567); !
Wenn jetzt die lustigen Leute auf die Idee mit der Liniendicke kommen, programmieren sie NICHT diese Methode da oben UM!! Nein, sie bauen einfach ein neues Interface und eine neue Methode:
INTERFACE GrafikDevice5 // wurde erst in DirectY Version 5.0 eingefügt
{
zeichneLinie(int, int, int);
}Jeder der "damals" sein Programm geschrieben hat und zeichneLinie mit 2 Parametern benutzt hat wird keinen Unterschied feststellen. Auch nach der Aktualisierung auf DirectY 5.0 und obwohl es neue Methoden gibt, funktioniert sein Programm trotzdem noch einwandfrei.
Denk' dran: DAS wäre nach dem alten "OO-pure" (s.o.) Konzept SO NICHT möglich...!!
Okay, mit Überladung könnte man manchmal noch einen reissen, aber
WAS wenn sich NUR INTERN was gravierendes ändert, zum Beispiel grundlegend andere Treiberansteuerung o.ä. ... !?!?DAMIT das SO klappen kann, muß sich COM natürlich auch an strikte Regeln halten:
JEDES COM-Interface definiert folgende Methoden:
AddRef()
Release()
QueryInterface()Zur Vereinfachung gibt es eine Basis-Interface-Klasse, die da IUnknown heißt, die genau diese Methoden enthält.
Jedes COM-Interface erbt also von dieser Basisklasse alle relevanten Methoden.Da man am Anfang immer davon ausgehen muß, daß noch keine Klasse, keine Komponente geändert (geupdatet) wurde, muß man immer die billigste / schlechteste / älteste Version zuerst QUERYen...
Man holt sich jetzt also GrafikDevice (in der ersten Version ohne Ziffer).
Da man aber weiß, daß man das DirectY 5.0 SDK draufhat, und in diesem das neue Interface GrafikDevice5 implementiert ist (was natürlich VIEL VIEL besser ist, da man jetzt die Liniendicke angeben kann)
, besorgt man sich das neue Objekt (und zwar ÜBER DAS ALTE - was man erst über COM holt):
Entsprechend:
GrafikDevice *gd = COM_Startup_GetTheFuckingInterface(GrafikDevice);
GrafikDevice5 *gd5 = gd->QueryInterface(GrafikDevice5);
Jetzt kann man das ALTE Objekt wieder killen:
gd->Release();
Für Leute die NUR DirectY 3.0 installiert haben, wird
gd->QueryInterface(GrafikDevice5);
natürlich fehlschlagen, für welche mit DirectY 5.0 (ODER BESSER !!) allerdings nicht.Die Methodennamen zur COM-Initialisierung sind natürlich nur symbolisch.
Ich hoffe, es wird klar, daß mein GrafikDevice und zeichneLinie() Beispiel schon sehr nah mit DirectX zu vergleichen ist...
DDRAWSURFACE3 und 5 etc.Auf jeden Fall kann ich jetzt gd5 benutzen...
Und könnte von da auch GrafikDevice7 QUERYen... (wenn's das denn schon gäbe)Aufgrund dieses Aufbaus ist DirectX (jetzt X - net Y) komplett abwärtskompatibel (sagen wir, ab Version 5.0 / bei DX 2.0+3.0 gab's ja noch Hick-Hack)!
Wenn ich meinen Code / Spiel nicht ändern will, MUSS ich das nicht, auch wenn eine neue Version von DirectX draussen ist, es wird trotzdem laufen!!
Natürlich kann ich dann nicht die neue Funktionialität nutzen!
- 3. Hab' ich ja eigentlich schon erklärt.
- 4. Hab' ich auch schon erklärt eigentlich.
Folgendes noch: Für die meisten DirectX-Klamotten gibt es vordefinierte Wrapper-Funktionen, die den ganzen COM-Kram kapseln, z.B. Direct3DCreate9().
Dieses macht intern genau das, was ich oben gesagt habe, also
d1 = COM_Get_Interface(Direct3D);
d3 = d1->QueryInterface(Direct3D3);
d4 = d3->QueryInterface(Direct3D4);
d9 = d4->QueryInterface(Direct3D9);
d1->Release();
d3->Release();
d4->Release();
return d9;Oder so ähnlich...
Für einige wie DirectPlay mußt Du die COM Initialisierung glaub' ich noch selber machen, dat is' aber auch kein Akt.
Guck' einfach in die DX Samples.Du brauchst nur QueryInterface() und Release() immer, AddRef() niemals!
Ich hoffe jetzt werden die Dinge klarer.
Und auch wenn es ein M$-Produkt ist, Du den Vorteil von COM zu schätzen lernst!
:-DDD
Falls Du oben genanntes echt noch nicht verstanden hast, vielleicht weitere Fragen stellen oder sich nochmal was in OOP reinhängen...
Hoffe geholfen zu haben.
Ciao,
SargeP.S.: Hab' jetzt Hunger...
- 1. COM steht für Component Object Model - d.h. ein "Modell" (a.k.a. Konzept) für komponentenbasierte "Objekte" (Objekte muß hier nicht unbedingt als Instanz einer Klasse angesehen werden).
-
HU!
Zum Verständnis gehe nochmals auf einige Punkte ein (Korrigiere mich falls ich Deine Erklärung falsch verstanden haben sollte):
Ich gehe davon aus, dass wir ein Objekt „GrafikDevice“ haben,
jenes Objekt besitzt die Methoden um eine Linie zu zeichnen. Nun bastele ich mir für mein Objekt ein Interface, um eine Schnittstelle anzubieten auf die eine externes Programm, etc. zugreifen kann.Richtig???
So, jetzt nun möchte man aber noch die Dicke der Linie mit als Parameter einpflegen, dazu bastelt man sich zusätzlich zum bestehenden Interfaces ein neues/weiteres welches die neue Methode deklariert.
Richtig ???
Um nun zu gewährleisten das dass Programm auch bei denen funktioniert die die Methode nicht kennen, muss man eine Abwärtskompatibiltät herstellen, d.h. ich muss zunächst das alte Interface einbinden
Hresult = DirectDrawCreate(NULL,&lpDD,NULL)
Besteht nun eine Verbindung kann ich über die QueryInterface Methode und einem Pointer (der auf das neue Interface zeigt) eine neues Interface einbinden. Anderes, ich muss erst das Interface DirectDraw einbinden bevor ich DirectDraw 2.0 einbinden kann.
Richtig???
Was ich nun aber an der ganzen nicht verstehe, warum muss man die Interface von Iunkwon ableiten und des weiteren verstehe ich noch nicht so ganz wie das Interface auf die Klasse hinter zugreift?
Danke
Tom79
-
Zu 1 & 2: Richtig
Zu 3: Du musst nicht unbedingt Interface1 einbinden, wenn dir Interface2 genügt.warum muss man die Interface von Iunkwon ableiten
Irgendwas Gemeinsames müssen alle Schnittstellen doch haben? Man hat versucht, alle Methoden, die jedes Objekt braucht, in einer Schnittstelle IUnknown unterzubringen.
wie das Interface auf die Klasse hinter zugreift
Interfaces sind abstrakte, virtuelle Basisklassen, falls es das ist, was du mit 'hinter' meinst.
-
Original erstellt von <Tom79>:
**Ich gehe davon aus, dass wir ein Objekt „GrafikDevice“ haben,
jenes Objekt besitzt die Methoden um eine Linie zu zeichnen. Nun bastele ich mir für mein Objekt ein Interface, um eine Schnittstelle anzubieten auf die eine externes Programm, etc. zugreifen kann.Richtig???**
Nein, nein. Ganz falsch.
Das war nur ein Beispiel!! Und zwar eines für COM.
Also, FALLS DU SELBER eine COM-kompatible API entwickeln willst, statt DirectX meinetwegen TomX, oder so, könntest Du SO vorgehen...
Es sollte nur COM etwas erklären.
Im Prinzip ist es ganz einfach.
Du wolltest DirectX & COM besser verstehen, und da DirectX auf COM basiert, hab' ich Dir über diesen Weg versucht, zu erklären, wie das alles zusammenspielt.Schau' Dir in der DirectX 9.0 SDK Doku meinetwegen unter DirectX Graphics - Reference - Interfaces z.B. "IDirect3D9 Interface" an:
Da steht unten:Interface Information
Inherits from IUnknown
Header d3d9.h
Import library d3d9.lib
Minimum operating systems Windows 98Wie Du siehst erbt IDirect3D9 also von IUnknown, genau was ich sagte.
Es halt also auf jeden Fall auch die COM-spezifischen Methoden AddRef(), QueryInterface(), und Release().Du könntest in einem Programm Dir das IDirect3D9 Interface SO holen:
HRESULT hr; IDirect3D9 *g_pD3D; hr = CoInitialize(NULL); // COM initialisieren hr = CoCreateInstance(CLSID_Direct3D9, NULL, CLSCTX_INPROC_SERVER, IID_IDirect3D9, (LPVOID*)&g_pD3D);
Dann würdest Du Dir quasi "direkt von COM" das Interface Direct3D9 holen.
Allerdings, wenn Du bei diesem Interface mal unter "Remarks" schaust, übernimmt diesen Job auch die einzige Funktion in Direct3D9:
Remarks
The IDirect3D9 is obtained by calling the Direct3DCreate9 function.
D.h. Du brauchst COM gar nicht direkt anzusprechen, um mit Direct3D9 zu arbeiten...!!
Ich hoffe Dir ist klar, daß das Besagte nur dazu diente, Dir COM zu erklären. Du mußt keine Interfaces selber machen oder so, um mit DirectX zu arbeiten. Du brauchst COM noch nicht mal (richtig) zu verstehen...!
Was ich nun aber an der ganzen nicht verstehe, warum muss man die Interface von Iunkwon ableiten und des weiteren verstehe ich noch nicht so ganz wie das Interface auf die Klasse hinter zugreift?
Man muß sie von IUnknown ableiten, wenn sie COM-kompatibel sein sollen.
Das ist so festgelegt!Nochmal:
Um 3D-Games oder so mit DirectX zu coden, mußt Du nicht wirklich über COM bescheid wissen...!!
-
Um 3D-Games oder so mit DirectX zu coden, mußt Du nicht wirklich über COM bescheid wissen...!!
Ja, was natürlich wiederum auf das zu entwickelnde Spiel ankommt. Denn sobald man z.B. zur Multithreading-Umgebung übergeht, um Buffer zu füllen oder zu bearbeiten, darf man nicht vergessen, dass ein neuer Thread erstens auch für COM per CoInitialize initialisiert werden muss und dass es spätestens ab dann losgeht, die Schnittstellen gemarshaled zu übergeben bzw., um es sich etwas einfacher zu machen, die GIT zu verwenden.
-
Original erstellt von RenéG:
Ja, was natürlich wiederum auf das zu entwickelnde Spiel ankommt. Denn sobald man z.B. zur Multithreading-Umgebung übergeht ...Sicherlich, und falls man auf X-Box portiert ... blablablupp!
Aber meine Angaben beziehen sich auch nur auf Tom's Satz:
bin seit kurzen dabei mich ich in C++ und DirectX einzulesen bzw. einzuarbeiten.