Artikel aus dem System Journal 3/2000

Von C++ Klassen zu COM-Objekten

Angenommen, Sie haben die Aufgabe, ein großes monolithisches MFC-Programm in einen COM-Server zu verwandeln. Die in Frage kommenden Klassen summieren sich auf einige hundert, die Anzahl der zu konvertierenden Methoden übersteigt die Tausendergrenze. Sie beschaffen sich Informationen über die Konvertierung von alten Projekten in MFC- oder ATL-COM-Server. Spätestens nach Lektüre dieser Informationen werden Sie graue Haare haben oder über einen Job-Wechsel nachdenken. Oder Sie beschaffen sich ein Tool, das das gros der Arbeit für Sie übernimmt.

Der Automator der deutschen Software-Schmiede Ablon tritt mit dem Anspruch an, solche Probleme zu lösen. Und soweit wir ihn testen konnten, lässt sich sagen, er schlägt sich dabei nicht schlecht.

Der Automator installiert sich als AddOn in Visual C++. Alles, was Sie zu tun haben, ist:

  • eine kleine Applikationsklasse zu schreiben, wobei Sie Hilfe von zwei Wizards erhalten, je für die Erstellung einer MFC-Exe und die Erstellung einer MFC-DLL
  • eine CPP-Datei zu erstellen, die eine oder mehrere Ihrere Headerdateien includiert
  • den Knopf für den Automator-Wizard zu drücken

Nun öffnet sich eine Baumansicht (Bild 1), in der Sie bequem die in COM zu exportierenden Klassen, Methoden und Attribute angeben können. Danach erzeugt der Automator eine Reihe von Automator-Maps, die den vielfältigen Maps der MFC und ATL ähneln. Nach Erstellen der Maps lässt sich mit einem Tool namens AutoOdl-Generator wahlweise eine IDL-Datei oder eine ODL-Datei erzeugen, oder ein Batch, der die Erzeugung vornimmt. Dieser Batch lässt sich als Verarbeitungsschritt einbinden.

Im obigen Beispiel würden Sie also einige hundert Header-Dateien in eine beliebige Anzahl CPP-Dateien includieren, für jede CPP-Datei einmal auf den Knopf drücken und eine Auswahl-Liste bearbeiten und nochmals OK drücken. Jetzt noch schnell den Batch für die Erstellung der IDL-Datei erzeugt, dann ist Ihre Umwandlungsarbeit in einen COM-Server erledigt. Zugegebenermaßen ist das bei einem Projekt der oben angebenen Größenordnung immer noch viel Arbeit, aber die Zeitersparnis gegenüber der Codierung mit ATL und MFC (bei Einsatz aller Wizards) schätzen wir aus dem hohlen Bauch etwa auf ein Fünftel.

 

   
Bild B1

Sicherlich beginnen Sie jetzt zweifelnd zu fragen, ob denn der Automator auch wirklich alle Parameter-Typen unterstützt, die Sie in Ihrem Projekt einsetzen. Ohne Anspruch auf Vollständigkeit haben wir folgende Eigenschaften gefunden:

  • CString und std::string werden automatisch erkannt und in BSTRs hin- und rückkonvertiert
  • Arrays werden als Safearrays dargestellt; soweit wir den Mechanismus verstanden haben, müssen diese als std::vektor-Arrays vorliegen. Bei hartcodierten Arrays scheint hier etwas Umwandlungsarbeit nötig zu werden.
  • Für selbstdefinierte Klassen lassen sich Konvertierungsklassen schreiben, die der Automator dann für die Konvertierung verwendet.
  • Alternativ lassen sich selbstdefinierte Klassen auch in COM-Klassen umwandeln, wobei die Parameterübergabe als Wert (by Value) möglich ist.
  • Methoden die mit Get und Set oder ähnlichen Prefixen beginnen, lassen sich in COM-Properties umwandeln. Die Prefixe lassen sich vor der Umwandlung selbst definieren.
  • Ebenso lassen sich Prefixe für Klassennamen angeben, so daß zum Beispiel aus "CKunde" die COM-Klasse "Kunde" wird.
  • Enums werden von C++ in COM übernommen; die Enum-Werte können in Script-Sprachen als String übergeben werden.
  • Globale und statische Mitglieder werden in entsprechende COM-Varianten umgesetzt. Der Automator erzeugt für jede Klasse ein Klassenobjekt, über das statische Mitglieder abgerufen werden können. Globale Funktionen oder Variablen erreicht man über das Applikationsobjekt.
  • Mit wenig Aufwand lassen sich aus Klasse COM-Collections erstellen.
  • C++ Exceptions, die von std::exception oder CException abgeleitet sind, können in COM-Fehlermeldungen umgewandelt werden. So lassen sich die Fehler in Visual Basic-Clients drekt abfangen und mit Err.Description Fehlertexte abfragen.
  • Mit wenig Aufwand lassen sich Klassen als Events definieren und anderen Klassen zuordnen, die dann als Event-Sourcen automatisch mit Verbindungspunkten ausgestattet werden.

Beim Herumprobieren mit dem Produkt zeigte sich, dass die meisten der Standard-Situationen ohne Probleme gemeistert werden konnten. Etwas Kopfzerbrechen bereiten die Umwandlung von Exceptions und die Erstellung von Collections - aber auch das gestaltet sich immer noch wesentlich einfacher, als wenn man das alles von Hand codieren müsste.

Eines fiel uns bei den Tests auf: Der Automator versieht umso besser seinen Dienst, umso sauberer die Anwendungen entworfen worden sind, die es zu konvertieren gilt. Drei Dinge sind unabdingbare Vorraussetzung:

  1. Eine durchgehende Namenskonvention, damit die Prefixe für den Automator leichter erkennbar sind.
  2. Eine klare Part-of-Hierachie der Klassen mit durchgängig gleichförmigen Design der 1:n Beziehungen
  3. Wenn Exceptions als COM-Fehler gemeldet werden sollen, dann ist eine klare Ausnahmestrategie vonnöten

Der Automator kommt mit einem sehr schönen Tutorial, das per Knopfdruck im Visual Studio aufrufbar ist. Der Beispiel-Code erscheint dann in den Source-Fenstern, während die Erläuterung in einem extra Fenster über der IDE schwebt - schön gelöst.

Sie können übrigens sofort mit dem Automator zu arbeiten beginnen. Eine funktional uneingeschränkte Version kann vom Ablon-Webserver heruntergeladen werden. Die Arbeit für nichtkommerzielle Zwecke ist kostenlos. Wer den Automator für die Produktentwicklung einsetzen will zahlt 1.900 EUR und kann gegen Auspreis noch diverse Wartungs- und Supportpakete erwerben. Wem der COM-Schuh drückt, der kann also ohne Risiko den Automator testen. Sobald klar ist, dass die Sache klappt, wird man den Preis für das Produkt auch gerne berappen.