COM Programmierung mit der ATL

Inhalte:
Thematik
Die ATL ist eine " Template" - basierte
Klassen- Bibliothek zur Erstellung
von COM Objekten.

Für wen ?
Dieser Kurs richtet sich an Programmierer
die COM-Objekte mit der Hilfe der
Active Template Library programmieren
wollen.

Das sollten Sie mitbringen !
Programmierkenntnisse in C++.

Was bringt es Ihnen ?

Dieser Kurs vermittelt die Kenntnisse,
um mit C++ und mit Hilfe der ATL
COM-Obekte zu erstellen.

Dauer 5 Tage
Seminare in C# oder in VB.NET

Einführung in .NET
Objektorientiert programmieren mit .NET
NET Framework Programmierung

Windows Forms Anwendungen
Vektor-orientierte Oberflächen mit WPF

Web Programmierung

Verteilte Anwendungen mit WCF

Andere Seminare
COM-Programmierung mit der ATL
OOP mit C++
Programmieren mit C
OOP mit Java
 

<<   Was ist COM ?

Eine Spezifikation. COM liefert ein Standardmodell zum Integrieren von Komponenten. Es folgt dem Trend eine Anwendung in mehrere wieder verwendbare Komponenten aufzuteilen.

Ziel von COM : 
Sprachunabhängigkeit - z.B. kann ein VB-Client eine C++ Komponente aufrufen. Ein weiteres Ziel ist die Ortsunabhängigkeit: die Ansteuerung der Komponente ist für den Client immer gleich, egal wo sich die Komponente befindet.

Sie kann sich innerhalb des Client-Prozesses befinden als Dll, innerhalb eines anderen Prozesses auf dem Client Rechner, als  getrenntes Exe-File. Oder sie befindet sich auf einem anderen  Rechner als Remote Komponente.

Eine Komponente kann als Dll oder als EXE File implementiert werden. Hierin enthalten sind ein oder mehrere COM-Objekte.

Das COM Objekt enthält die Methoden, die der Benutzer über einen Zeiger auf ein Interface (Schnittstelle)  aufruft.
Das Com-Objekt exportiert seine Funktionalität in Form eines Interfaces. In C++ wird einInterface über virtuelle abstrakte Methoden realisiert - Polymorphismus lässt grüßen.

Was ist Polymorphismus ?
Zum einen virtuelle Funktionen, die im COM-Objekt implementiert werden müssen. Zum anderen auch der Zugriff vom Client stets über einen Basisklassen Zeiger.Die Basisklasse ist hier das Interface. Das ist auch der Grund, warum in COM 
grundsätzlich der Zugriff auf eine Funktionalität im COM-Objekt nur über einen 
Interface Pointer erfolgt.

Wie wird das alles in C++ implementiert ?

In welchen Sprachen können COM-Objekte entwickelt und verwendet werden ? In den Sprachen, die es erlauben Funktionen über Funktionszeiger anzusprechen d.h. in allen in Sprachen, außer in Scriptsprachen, dafür gibt es aber auch einen Weg.


<<   COM-Objekte mit der COM-API erstellen


Was ist ein Interface ?
Ganz allgemein eine Gruppierung von Funktionen für eine bestimmte Aufgabe. So ermöglicht das Standard Interface IStream das Schreiben in einen Stream und das Lesen daraus. Diese Funktionalität kann in einem eigenen COM-Objekt 
implementiert werden. Clients können dadurch in einer standardisierten Weise auf das COM-Objekt zugreifen.    
 
Ein einmal festgelegtes Interface darf nicht mehr geändert werden, die VTable darf sich nicht ändern.

Was sind GUID‘s : 128 Bit breite Zahlen, sie werden verwendet um Interfaces, Klassen und Type - Libraries eindeutig zu identifizieren.
Sie werden in C++ als Struktur verwendet ( Es gibt keinen 128 Bit Datentyp).

Jedes COM-Objekt braucht eine IUnknown Interface Implementierung.
Über die enthaltenen Methoden AddRef() und Release()  wird die Lebensdauer des 
COM-Objekts gesteuert, über QueryInterface(..) wird nach weiteren Interfaces gefragt.

Was ist ein COM-Server ?
Eine Komponente, eine DLL oder ein EXE File, die eine oder mehrere COM Objekte enthält .

Der Ort des Servers sollte für den Client keine Rolle spielen, für den Client ist der Aufruf immer "InProcess". Dadurch ist der Aufruf  immer gleich. Bei einem EXE-Server ist kein direkter Zeiger möglich, dann erhält der Client einen Zeiger auf einen Proxy.

Wie instantiiert der Client die COM-Objekte innerhalb des COM-Servers ?
Über eine ClassFactory. Diese ist selbst ein COM-Objekt und muss im COM-Server implementiert werden. Da Sprachabhängigkeit erwünscht ist, wrappt die ClassFactory den "new" Operator. Wie ist der genaue Vorgang ?

Die CLSID‘s aller COM-Objekte eines COM-Servers müssen in die Registry eingetragen werden. Als Minimum ist der Ort des Servers einzutragen: Die CLSID des COM-Servers wird unter HKEY_CLASSES_ROOT\CLSID eintragen.

Wie findet COM den gewünschten Server ? Wie ist der genaue Vorgang der Aktivierung ?

Wir steuern einen InProcess COM-API Server mit einem Console C++ Client an.

<<   Mehrfach-Vererbung

Es gibt 2 Verfahren zur Implementierung von COM-Objekten mit mehreren Interfaces. Multiple-Inheritance (Mehrfachvererbung), diese wird auch von der ATL verwendetdazu wird das COM-Objekt von allen Interfaces abgeleitet.
Alle Methoden aller Interfaces müssen dann im COM-Objekt implementiert werden. Vorteil :Code ist intuitiver, auch performanter.
Nachteil: Namenskonflikte bei gleichen Methoden in unterschiedlichen Interfaces, sie sind eher selten aber lösbar.

Embedding mit Nestet Klassen, so werden Interfaces in der MFC implementiert.
Vorteil: keine Namenskonflikte
Nachteil: Code ist gewöhnungsbedürftig. Für jedes Interface wird eine eigene Klasse erstellt.


<<   Einführung in die ATL


Wie unterstützt uns die ATL bei der Programmierung von COM-Objekten und Servern ?
Welche Teile werden dabei von der ATL übernommen ? Die Projekt-Struktur.

Was können die Wizards ? Was können sie nicht ?
Die beiden Wizards:
Der ATL COM AppWizard erstellt das Housing, d.h. die Dll oder das Exe File.
Der ATL Objekt Wizard erstellt COM-Objekte. 

Was liefert uns die ATL ?
Support für Custom Interfaces , eine Implementierung für duale Interfaces. Eine drastische Vereinfachung zur Implementierung von Connection Points für das Eventhandling in COM.
Eine Implementierung von IUnknown, IClassFactory und IDispatch. Support für wieder verwendbare Objekte in COM über Aggregation.
Error Support mit der ATL. Alle Thread Modelle werden unterstützt. Code ist optimiert.Ein Script für die Registrierung wird erzeugt.

Was sind die wichtigsten ATL-Klassen ?

Wie schaut die Klassenableitung aus ?
Die ClassFactory der ATL erstellt ein CComObject oder ein CComAggObject.
Hier ist IUnknown für unsere Klasse implementiert, dieses Objekt stellt auch die VTBL zur Verfügung.
Die IUnknown Implementierung muss sich in der am weitesten abgeleiteten Klasse befinden, das bestimmt die Mehrfachvererbung, daher wird unsere Klasse noch einmal abgeleitet.

Das erste Interface bekommen wir mit dem ATL Objekt Wizard beim Erstellen des COM-Objekts. Weitere Interfaces fügt man am besten in der IDL von Hand hinzu .

Wie ist die Vorgehensweise bei Custom Interfaces, wie bei den Standard Interfaces beispielsweise bei einem IStream oder IPersist Interface ?

Wie werden GUID's erzeugt ?

Außerdem gibt es noch einen weiteren Wizard, den Implement Interface Wizard. Implementiert der denn schon unsere Interfaces ? Dem ist leider nicht so.

<<   Native COM Support für die Client-Programmierung

Der Native COM Support unterstützt uns in der Client Programmierung.
Was stellt er im einzelnen zur Verfügung ?

SmartPointer:rtPoinDas "Buchführen" der Interface Zeiger mit AddRef() und Release() ist gerade in tief verschachteltem COM-Code nicht mehr trivial. SmartPointer können unseren Code stark vereinfachen. Sie sind Klassen, die einen Interface Zeiger kapseln.
Durch geschickte Operator Überladung kann man sie verwenden wie normale Interface Zeiger. 

Verstehen wir die Anwendung des IUnknown Interfaces an sich und wissen wir, wann ein
QueryInterface(..) erfolgen muss, dann macht uns das Verwenden der SmartPointer auch keine Probleme, denn auch sie haben ihr Eigenheiten. Auch die ATL verwendet SmartPointer, sie hat dafür eigene Klassen.

Was bekommen wir noch ? Wrapper Klassen. KlaWrapper Klassen werten den HRESULT der Methoden der COM-Komponente aus und werfen beim Client eine Exception. Es gibt in COM kein durchgängiges Exception Konzept vom Server wie z.B. bei CORBA.

Wrapper für Propertys:  s: 
Ursprung hat das in Visual Basic, wo man Propertys schon lange kennt. 
Propertys sind public Zugriffsfunktionen für private Variable im COM-Objekt.
Sie werden im Client wie ein Variablen Zugriff verwendet z.B. ohne Klammern.

Es gibt jede Menge Makros, die man nicht alle im Detail kennen muss, eine Zuordnung
sollte aber möglich sein.

Ausgelöst wird der Native COM Support durch eine Import Anweisung,
wir erhalten 2 Files im Debug Verzeichnis der Client Anwendung.


<<   Error Handling in COM

Die ATL unterstützt Fehler Meldungen im Server. Das erfolgt für jedes Interface getrennt.
Die Fehlermeldung wird einem Error Objekt übergeben.

Die Implementierung erfolgt in CComCoClass. Sie wrappt das Interface ICreateErrorInfo
mit 6 überladenen Funktionen.

Das erfordert, daß der Server ISupportErrorInfo implementiert. COM wertet das aus und 
wirft beim Client eine Exception. 

Die Fehler Unterstützung erfolgt für jedes Interface getrennt.


<<   Das IDispatch Interface

Es gibt Sprachen, die keinen Zugriff auf virtuelle Methoden Tabellen (VMTs) haben.
Wie ist es aber möglich, dass Anwendungen wie der Internet Explorer
AktiveX Controls ansteuern können, diese sind ja auch COM-Objekte und sehr
komplexe dazu. In COM wird aber immer nur mit Interfaces gearbeitet !

Die Lösung: Der Internet Explorer hat dazu ein ganz spezielles Interface
implementiert, das Interface IDispatch. Über dieses Interface kann jedes COM-Objekt
angesteuert werden, sofern es auch dieses IDispatch Interface implementiert hat.

Über dieses Interface können wir somit ein COM-Objekt nach einer bestimmten
Methode fragen. Ist die Methode vorhanden, erhalten wir eine Dispatch ID für einen
anschließenden Aufruf.


<<   Duale Interfaces

Dispatch Interfaces sind von natur aus erheblich langsamer als Custom Interfaces.

Die Lösung:
Das duale Interface ist eine Kombination eines Custom Interfaces mit einem
IDispatch Interface. Die ATL stellt dafür eine Implementierung zur Verfügung.

Somit können "VTBL-Clients" auf das schnelle Custom Interface zugreifen,
"IDispatch-Clients" auf das langsamere IDispatch Interface.
Eigentlich ideal, aber wir sind in den Datentypen eingeschränkt: Es stehen uns nur die
Automations-Datentypen zur Verfügung, also keine Strukturen etc.

Es gibt noch einen weiteren Nachteil. IDispatch Clients können keinen QueryInterface
machen, dafür gibt es aber einen Work Arround.


<<   Wiederverwendung in COM

Objektorientierte Sprachen ermöglichen die Vererbung auf  Sourcecode - Ebene.
COM erlaubt die Wiederverwendung von binären Objekten.

Dafür gibt es 2 Arten: 
COM-Containment und COM-Aggregation
Wie sieht die Implementierung dazu aus ?


<<   Events

Wie funktionieren Events in COM, aus der Sicht von Client und Server ?
Wie erzeugt ein COM-Objekt Events mit Custom- und Dispatch-Interfaces ?
In COM werden dazu Connection Points verwendet.

<<   Datenhandling bei Custom Interfaces

Einführung in die Remoting Infrastruktur bei COM.
Marshaling mit der Proxy / Stub Dll

BSTR, der Datentyp für Strings in COM

Speicherhandling bei der Übergabe von Daten zwischen Client und Server
Wer legt an ? Wer gibt frei ?

Übergabe von Strukturen

Übergabe von Arrays

Übergabe von Zeiger

<<   Thread Modelle

COM und mehrere Threads.
Die Thread-Modelle MTA und STA

OutOfProcess Server

Szenarios: 
STA Client  und STA Server
Mixed Modelle
MTA Client  und MTA Server

Worker Threads verwenden COM
Der FTM