![]() |
|
URL dieses Artikels:
zu Ausgabe:
3.2007
Flexible Software in C++ gestalten
Wie plattformunabhängige Klassenbibliotheken den Entwickleralltag vereinfachen
Dr. Christian Dietrich
Will man effiziente Software für mehrere Zielsysteme mit plattformunabhängigem Quellcode bereitstellen, ist C++ meist eine gute Wahl, weil C++ die Kombination aus effizienter maschinennaher Programmierung und moderner objektorientierter Programmierung erlaubt. Allerdings ergibt sich auch ein Mehraufwand. Denn zum einen ist der Quellcode für die verschiedenen Architekturen zu übersetzen und zum anderen sind die Programme auf den einzelnen Zielsystemen zu testen. Der Aufwand lohnt sich dennoch, denn die Bedeutung plattformunabhängiger Software nimmt stetig zu, sorgt für höhere Anwenderakzeptanz und macht den Entwickler insgesamt flexibler. Mit der Klassenbibliothek Qt und den zugehörigen Werkzeugen kann man die Aufgabe zudem einfacher gestalten als vielfach angenommen.
Nach wie vor fällt mit gutem Grund bei der Entwicklung umfangreicher, effizienter und betriebssystemunabhängiger Anwendungen die Wahl häufig auf C++. Betriebssystem-, compiler- und prozessorspezifische Unterschiede müssen in diesem Szenario keine Kopfschmerzen bereiten, denn man kann sie oft plattformabhängig implementieren. Ist dies nicht möglich, lässt sich der Code dem Compiler durch bedingte Übersetzung mithilfe des Präprozessors "unterschlagen". Der Quellcode teilt sich somit in einen großen Anteil portablen Quellcode und einen kleinen Anteil plattformspezifischen Code auf. Listing 1 zeigt anhand der Beispiel-Funktion mysleep deutlich, wie man plattformabhängigen Code am Compiler vorbeischleust. Listing 1Prominente Beispiele hierfür sind der Internetbrowser Firefox, das E-Mail-Programm Thunderbird oder das Grafikprogramm GIMP. Beachtet man einige Rahmenbedingungen, so lassen sich weite Teile des Quellcodes portabel implementieren, da die International Organisation for Standardisation (ISO) C++ normiert hat. Bei Anwendungen, die keine Treiber und keinen hardwarenahen Code enthalten, kann der plattformspezifische Code auch oft entfallen. Eine immense Arbeitserleichterung kann man durch die Standard Template Library (STL) erzielen. Denn sie bietet effiziente Container-Klassen in Form von Vektoren, Listen, Maps oder Stacks. Darüber hinaus enthält sie Algorithmen à la Binärsuche, Sortieren sowie Merging. Und schließlich ermöglicht sie dem Entwickler, auf Iteratoren und Funktionsobjekte zurückzugreifen. Plattformunabhängige Bibliothek hilft in vielen Situationen Weil die Darstellung grafischer Steuerelemente aufgrund der fehlenden Funktion im C++-Sprachumfang problematisch ist, kommen vielfach systemabhängige Bibliotheken wie die Microsoft Foundation Classes (MFC) unter Windows oder OSF/Motif unter Unix zum Einsatz. Schließlich basiert die grafische Ausgabe der Betriebssysteme – insbesondere Unix/Linux, Windows und Mac – auf unterschiedlichen Prinzipien und ist eng an das Betriebssystem gekoppelt. Dies führt jedoch zu dem entscheidenden Nachteil, dass die Plattformunabhängigkeit des Quellcodes verloren geht, weil die Sprach-Syntax zum Ansprechen der grafischen Fensterobjekte abhängig von der verwendeten Bibliothek ist. Eine Bibliothek mit plattformunabhängiger Schnittstelle zur Darstellung der grafischen Steuerelemente kann diese Hürde jedoch aus dem Weg räumen. Qt ist hier eine mögliche Option! Denn bei dem Qt-Toolkit handelt es sich um ein umfangreiches Framework zur Entwicklung portabler Software basierend auf C++. Allerdings ist Qt ebenfalls an systemabhängige Bibliotheken gebunden. Diese basieren jedoch größtenteils auf plattformunabhängigem Quellcode mit dem entscheidenden Vorteil, dass die Bibliothek dem Anwendungscode eine betriebssystemunabhängige Schnittstelle zur Verfügung stellt. Damit bleibt die Syntax des Quellcodes unverändert, was den Anteil des portablen Quellcodes stark erhöht. Die folgenden Qt-Bibliotheken stehen zur Verfügung:
Qt im Kurzüberblick Qt steht gegenwärtig in der Version 4.2 und für eine Vielzahl von Plattformen in einem dualen Lizenzsystem zur Verfügung. Der Hersteller Trolltech bietet auf seiner Website eine kostenfreie Open-Source-Edition mit einer GNU General Public License (GPL) zum Herunterladen an. Daneben kann man auch eine kostenpflichtige, kommerzielle Lizenz erwerben, für die Trolltech im Gegensatz zur freien Version Produktsupport anbietet. Letztere ist allerdings nur dann notwendig, falls mit Qt Produkte entwickelt werden, die nicht unter einer freien Lizenz stehen. Beim Funktionsumfang der Open-Source-Edition gegenüber der kommerziellen Version ergeben sich nur geringfügige Einschränkungen. Maßgebliche Stadien und Entwicklungen Maßgeblich für Version 4.0 waren folgende Technologien:
Selbst in der Open-Source-Version bietet Qt umfangreiche Funktionen in über 400 Klassen. Wesentliche Komponenten sind:
Abb. 1: Der Qt-Linguist bietet eine Oberfläche, um Programme in verschiedene Sprachen zu übersetzen. Dies vereinfacht die Arbeit, denn der Übersetzer muss sich nicht in den Quellcode einarbeiten und kann die Texte zu einem späteren Zeitpunkt dynamisch anpassen oder in weiteren Sprachen zur Verfügung stellen. Plattformunabhängigkeit durch Qt Die oben bereits angerissenen Makefiles sind für viele Entwickler im C/C++-Kontext ein eher ungeliebtes Stiefkind, insbesondere dann, wenn die Dateiabhängigkeiten im Makefile angegeben werden müssen. Durch qmake, einen Generator für Makefiles, verlieren die plattformspezifischen Makefiles deutlich an "Schrecken", da diese automatisch durch qmake erzeugt werden. Die gewohnten Einstellungen können in einer plattformunabhängigen Projekt-Datei eingegeben werden, welche lediglich Anweisungen, die man für die Erstellung der Makefiles benötigt, enthält. Mit dem Befehl qmake-project ist es sogar möglich, die Projektdatei völlig automatisch zu erstellen. Empfehlenswert ist dieser Befehl allerdings nur, wenn mit einem neuen Projekt begonnen wird oder ein bestehendes Projekt mit qmake übersetzt werden soll. Im Verlauf des Entwicklungsprozesses wird die Projektdatei typischerweise an die Erfordernisse angepasst. So lassen sich je nach Zielsystem selbst unterschiedliche Sourcecode-Dateien für die Erstellung der Makefiles angeben (Listing 2). Listing 2Ein weiteres gängiges Problem ist die Anpassung der Anwendung an typische Eigenschaften des Betriebssystems. Diese betriebssystemspezifischen Modifikationen kann aber auch Qt übernehmen. Dies erleichtert nicht nur die Arbeit des Entwicklers, sondern erhöht auch die Qualität der Software. Ein konkretes Beispiel ist etwa das Speichern persistenter betriebssystemunabhängiger Settings (Listing 3). Diese werden von der Klasse QSettings implementiert. Die Memberfunktionen writeEntry und readNumEntry speichern oder lesen Integer-Werte. Die Identifikation des Settings erfolgt über einen String, den key. Während der Qt-basierte Quellcode identisch ist, speichert die Qt-Library die Daten betriebssystemtypisch:
Listing 3Die Betriebssystemabhängigkeit der Verzeichnisstruktur und der Pfadangaben hat sich bisweilen als nervenaufreibendes Problem erwiesen, weil sowohl die Begrenzer als auch die Verzeichnisstruktur abhängig von dem verwendeten Betriebssystem sind. Eine große Hilfe zur Vermeidung solcher Probleme ist die Klasse QDir, denn sie kann einige betriebssystemspezifische Unterschiede ausgleichen, indem man den Verzeichnisnamen mit ihr manipuliert. Den Begrenzer (unter Windows "\" und unter Linux/Unix "/") stellt Qt dabei durch die statische Memberfunktion QDir::separator() zur Verfügung. Listing 4 zeigt die Manipulation des Verzeichnisnamens mithilfe der Klasse QDir. Dabei erzeugt man einen String, der auf das Verzeichnis mit dem Namen Test im Home-Verzeichnis des aktuellen Benutzers durch die Verkettung dreier Strings (alle vom Typ QString) verweist. Listing 4Sind all diese "kleinen Problemchen" ausgemerzt, steht der Entwicklung von portabler Software im Grunde nichts mehr im Wege. Fazit: Vorteile überwiegen deutlich Der Mehraufwand für die Entwicklung plattformunabhängiger Software in C++ ist vergleichsweise gering, erfordert jedoch entsprechendes Know-how. Systemabhängige Bibliotheken, deren Quellcode nicht zur Verfügung steht, sollte man vermeiden, weil diese das Produkt einengen. So lässt sich ein Programm beispielsweise nicht auf ein weiteres Zielsystem portieren, wenn nur eine der verwendeten Closed-Source-Bibliotheken nicht für dieses System zur Verfügung steht. Anders verhält es sich bei offenen Bibliotheken, denn diese kann man im Notfall anpassen und für ein weiteres Zielsystem übersetzen. Abschließend kann man sagen, dass die Relevanz der Plattformunabhängigkeit kontinuierlich wächst. Im Bereich der Standardsoftware erhöht sie die Akzeptanz der Software, weil der Anwender ein vertrautes Programm auf verschiedenen Systemen verwenden kann. Im Bereich der Individualsoftware kann man durch geringen Aufwand besser auf Kundenwünsche reagieren, was den Entwickler insgesamt flexibler macht. Auf den Punkt gebracht: Die Vorteile dieses Ansatzes überwiegen seine Nachteile deutlich. |
||
|