Die Component Library for Cross-platform (CLX) überbrückt für C++-Projekte die Welten Windows/Delphi und Linux/Kylix. Dieser Artikel zeigt die Praxis: die Portierung eines Delphi- und C++Builder-Programms nach Linux, eines Delphi-Programms nach Kylix für C++ sowie die eines Delphi-VCL-Programms in CLX.
Viele große Open-Source-Projekte wie Apache, Open Office oder Mozilla beschränken sich nicht auf eine Plattform oder einen Prozessortyp. Den Entwicklern ist es wichtig, ihr Programm für viele Betriebssysteme lauffähig zu gestalten. Auch kommerziellen Programmen erschließt sich durch eine Portierung ein neuer Markt. Ein Mittel kann das Gespann Delphi/Kylix sein.
Mit Kylix 3 ist es endlich möglich, Delphi-6/7- und C++Builder-6-Projekte (die C++-IDE von Borland) von Windows auf Linux zu portieren. Mehr noch: Man kann neue Projekte gleich so entwickeln, dass deren Portierung zügig abläuft. Die längste dem Autor dieses Beitrags bekannte Zeit, ein sauberes Delphi-CLX-Projekt unter Linux zum Kompilieren zu überreden, ist die Colliers-Case-Study[2] – die Portierung dauerte gerade mal zwei Stunden.
Dieser Workshop beschreibt, wie man vorhandene Delphi/VCL-Projekte (Visual Component Library) in CLX-Projekte (Component Library for Cross-platform) umwandelt und wie CLX-Projekte auf der jeweils anderen Plattform kompilieren. Der erste Abschnitt – Portierung des Thread-Beispiels – wird zunächst ein kleines Delphi-VCL-Projekt in Kylix für Delphi laden.
Der zweite, sehr kurze Teil – Portierung eines Delphi-CLX-Projekts in Kylix – kompiliert ein einfaches Delphi-CLX-Programm mit Kylix. Am Ende stehen das Schreiben eines VCL-Programms im C++Builder, das Konvertieren in ein CLX-Programm und schließlich das Einbinden in das portierte Delphi-CLX-Programm.
Welche Entwicklungsplattform verwenden?
Es ist empfehlenswerter, Projekte mit Linux CLX zu entwickeln und später für Windows zu kompilieren als umgekehrt: Nicht nur ist Kylix billiger als Delphi oder C++Builder – hier müsste man korrekterweise sogar mit der Summe aus Delphi und C++Builder vergleichen -, unter Kylix ist auch die Gefahr geringer, versehentlich plattformabhängigen Code zu schreiben. Die aktuellen Versionen von Delphi und C++Builder enthalten eine Lizenz für den entsprechenden Kylix-Teil: Delphi für die Delphi-IDE unter Kylix sowie C++Builder für die C++Builder-IDE. Das Produkt Kylix und die kostenlose Kylix Open Edition zum Einsatz in Open-Source-Projekten enthalten sogar beide IDEs.
Es gibt ein Tool, um Projektdateien des C++Builders in Kylix zu importieren, aber es gibt wohl kein Tool, das eine Umwandlung von VCL- in CLX-Quelldateien durchführt. Abhängig vom Projekt kann die Umwandlung nämlich vom Hinzufügen einiger »Q«-s in Unit-Namen bis zum kompletten Wechsel der Datenbank- und Intra- und Interprozesskommunikation reichen (CLX unterstützt weder die Borland Database Engine BDE noch Windows-proprietäre Messages).
Wie eine manuelle Umwandlung abläuft, beschreiben etwa Dr. Bob unter[1] und selbstverständlich die Handbücher (“Delphi 7”, Kapitel 15.2 und folgende, “C++Builder 6”, Band 1, Kapitel 14.2 und folgende). Nach dieser Umwandlung liegt keine “native Linux-Version” des Quelltextes vor, sondern eine CLX-Version, deren Quelldateien im Idealfall plattformunabhängig sind.
Beachtenswert ist, dass unter Windows die scheinbar unwichtige Umbenennung der »dfm«-Dateien in »xfm«-Dateien darüber entscheidet, welchen Code die IDE aus den in den entsprechenden Dateien enthaltenen Formulardefinitionen generiert: CLX-Code bei »xfm« und VCL-Code bei »dfm«-Dateien. Diese Umbenennung ist beim Portieren immer der erste Schritt, gefolgt von der Anpassung von »{$R *.dfm}« in »{$R *.xfm}« in der entsprechenden Quelldatei.
Benennt man diese Dateien nicht um und nimmt scheinbar korrekte Anpassungen in den Quelldateien vor, zum Beispiel die Verwendung von »QForms« statt »Forms«, fügen Delphi und C++Builder beim nächsten Speichern automatisch die jetzt “fehlende” Forms-Unit beziehungsweise -Headerdatei wieder in den Quelltext ein.
Grund: Beide schließen aus der Dateiendung der »dfm«-Datei auf ein VCL-Projekt mit einem Formular, das die Unit »Forms« erfordert. Ist die aber umbenannt, werden Delphi und C++Builder auch unter Windows schon beim Laden einen Teil der entsprechend benötigten CLX-Units verwenden. Kylix verwendet immer CLX-Units.

Abbildung 1: Eine ehemalige VCL-Thread-Anwendung als CLX-Anwendung unter Linux. Sie klassifiziert unterschiedliche Algorithmen anhand des Sortierungsgrads des Feldes. Alle Threads beziehungsweise Algorithmen starteten zum selben Zeitpunkt mit gleichen Linienlängen.
Portierung des Thread-Beispiels
Auf der CeBIT 2003 wurde der Autor mehrfach gefragt, ob das Multithreading des C++Builders portabel oder durch spezielle Forks oder Ähnliches unter Linux für jede Anwendung neu zu schreiben sei. Die Antwort: Entwickler können zwar unter Kylix auf Glibc-Funktionen zurückgreifen und speziell auch »fork« nutzen (es versteht sich, dass solche Dinge in einem »#ifdef«-Block eben nur für diese Plattform geschehen sollten), allerdings sind auch die CLX-Thread-Klassen unter Kylix für Delphi und Kylix für C++ nutzbar.
Hier der Beweis mit einer gleichzeitigen Umwandlung von VCL in CLX: Kopie-ren Sie »Delphi7DemosThreads« auf Ihre Linux-Partition und benennen Sie »thsort.dfm« in »thsort.xfm« um. Öffnen Sie »ThSort .pas« in einem Editor und ändern »{$R *.dfm}« in »{$R *.xfm}«. Benennen Sie außerdem »thrddemo. res« in »ThrdDemo .RES« um. Dem Öffnen in Kylix für Delphi steht nun nichts mehr im Wege. Die darauf folgende Borderstyle-Meldung beruht auf einer Eigenschaft, die in CLX-Forms fehlt, und darf ignoriert werden.
Wenn Sie das Programm zu starten versuchen, stoßen Sie zunächst auf die nicht auffindbare Unit »Forms« in »thrddemo«. Ändern Sie diese in »QForms«. Unter CLX bleiben in diesem Fall zwar Eigenschaften, Methoden und Klassennamen gleich, jedoch sind sie teilweise in anderen Units abgelegt.
Unter dem Reiter »ThSort« löschen Sie jetzt die nicht portablen Units »Windows« und »Messages«. »Controls«, »StdCtrls« und »ExtCtrls« wurden durch »QControls«, »QStdCtrls« und »QExtCtrls« ergänzt – sind also in der Version ohne »Q« überflüssig. Ersetzen Sie »Graphics« durch »QGraphics«, »Forms« durch »QForms« und »Dialogs« durch »QDialogs«. Diese Ergänzung wurde in »SortThds« mangels Formulardefinitions-Datei nicht automatisch vorgenommen, daher müssen hier »Graphics« und »ExtCtrls« ihr »Q« manuell verpasst bekommen.
Sie sollten jetzt eine funktionsfähige CLX-Version der ehemaligen VCL-Anwendung haben. Wenn Sie sich diesen Spaß in Kylix für C++Builder nicht entgehen lassen wollen, liegt das Beispiel dort im Verzeichnis »Examples/Apps/ Threads«. Lassen Sie zunächst das Project Conversion Utility (siehe Kasten “Project Conversion Utility”) über die Projektdatei laufen.
|
Project Conversion |
|---|
|
Das Utility ist erhältlich in der »eToys«-Sektion von[3]. Es installiert sich in der Kylix-C++-IDE beziehungsweise in C++Builder unter »Tools | Project Conversion Utility«. Diese Projektkonvertierung betrifft nur die Projektdatei von C++Builder- respektive Kylix-für-C++-Projekten und ändert die Quelldateien nicht, übernimmt also auch keine Konvertierung von VCL in CLX. Die Windows-Version kann Kylix für C++-Projektdateien in C++Builder-6-Projektdateien umwandeln, die Linux-Version C++Builder-6-Projektdateien in Kylix für C++-Projektdateien. Notwendig ist dies derzeit noch wegen unterschiedlicher Switches beider Compiler. |
Die nächsten Schritte
»{$R *.dfm}« heißt selbstverständlich »#pragma resource “*.dfm”« und wird auch hier in »*.xfm« geändert. Viele »vcl.h«-Include-Dateien sind zusätzlich in »clx.h« umzubiegen. In »sortthd.cpp« wird »Synchronize(DoVisualSwap);« zu »Synchronize(&DoVisualSwap);«, denn hier differieren CLX- und VCL-Aufrufsyntax. Eine gute Idee ist, in »thsort.cpp« »random(170);« durch »random()%170;« zu ersetzen, da Linux\’ Random-Funktion manuell auf einen Wertebereich eingeschränkt werden. Ein entsprechendes »#ifdef« hält die Version-Windows dann kompatibel.
Der Haken am Port der C++-Version ist, dass die Kylix-Entwickler offenbar gute Gründe hatten, in » Kylix3Pfad/examples /c/threads/« dynamische statt statischer Arrays einzusetzen. Zwar läuft die Version mit statischen Arrays los, klickt man allerdings auf den »Start Sorting«-Knopf, vorzugsweise kurz nach dem Ende der Sortierung, erhält man spätestens beim zweiten Klick eine »EAccessViolation«. Die Rückportierung auf Windows jedoch scheint dieses Verhalten nicht zu zeigen.
Portierung eines Delphi-CLX-Projekts in Kylix
Kopieren Sie sich ein Delphi-CLX-Projekt, zum Beispiel den CLX Explorer » Delphi7-PfadDemosClxClxExplorer«, in Ihre Linux-Umgebung, starten Sie Kylix für Delphi (»startdephi«) und öffnen das Projekt. Ein Klick auf »Start« sollte die Anwendung unter Linux kompilieren und starten (Abbildung 2). Fertig!
Ein C++Builder/VCL-Projekt in Kylix
Um die Sache etwas komplizierter zu machen, geht das folgende Szenario davon aus, dass Ihr bestehendes Projekt unter dem C++Builder als VCL-Projekt vorliegt statt unter Delphi als CLX-Projekt. In diesem Falle ergibt sich nämlich folgende Arbeitsweise: Starten Sie den C++Builder und besetzen Sie eine VCL-Anwendung (»Datei | Neu | Anwendung«) mit einem Button und einem TImage-Control.
Ändern Sie die Name-Eigenschaft des Formulars auf »ImageForm«, um später Kollisionen mit »Form1« zu vermeiden, und die »Stretch«-Eigenschaft des »TImage« auf »true«, um Bilder auf die TImage-Größe zu skalieren.
Der Button soll die Sichtbarkeit des Bildes ändern. Doppelklicken Sie dazu auf den Button und fügen Sie entsprechenden Code in den Eventhandler ein: »Image1->Visible=!Image1->Visible;«. Speichern Sie danach im Linux-Share und schließen dieses Projekt.
Benennen Sie nun in dem Linux-Share »Unit1.dfm« in »Unit1.xfm« um. Öffnen Sie »Unit1.cpp« in einem Editor und ändern die Zeile »#pragma resource *.dfm« in »#pragma resource *.xfm« in »Unit1 .cpp«. Ändern Sie ebenfalls »#include <vcl.h>« in »#include <clx.h>« und speichern diese Änderungen.
Starten Sie dann in Kylix für C++ das Project Conversion Utility (siehe Kasten). Wenn Sie die exportierte Datei nun in Kylix öffnen, fügt Kylix beim nächsten Speichern in »Unit1.h« die benötigten CLX-Units ein. In »Unit1.h« dürfen Sie nun »#include <Controls.hpp>«, »#include <StdCtrls.hpp>« und »#include <ExtCtrls.hpp>« löschen, da sie durch die automatisch eingefügten Includes (»QControls«, »QStdCtrls« et cetera) durch die CLX-Versionen der VCL-Header ersetzt wurden. Noch zu ändern ist »#include <Forms.hpp>« in »#include <QForms.hpp>«.
Starten Sie ein so geändertes Projekt unter Windows, läuft es durch und beendet sich sofort selbst. Kylix meldet, keine Headerdatei mit dem Namen »vcl.h« (diesmal in »Project1.cpp«) zu finden. Sobald Sie diese Datei (»Projekt | Quelltext anzeigen«) ebenfalls CLX-konform ändern (»#include <clx.h>« statt »#include <vcl.h>«), haben Sie ein funktionsfähiges CLX-Projekt.
Um die Delphi-Fähigkeiten von Kylix für C++ nochmals zu verdeutlichen, können Sie gern den in Delphi beziehungsweise Kylix für Delphi vorhandenen CLX Explorer in Kylix für C++ in Ihr Projekt einbinden. Denn schließlich beherrscht der C++Builder sein Delphi schon seit Ewigkeiten.
|
Listing 1: |
|---|
// Überprüfen, ob ein Eintrag selektiert ist, // der kein Verzeichnis ist if ((FileListView1->SelCount>0)&&((FileListView1-> Selections[0]->SR.Attr&faDirectory)==0)) // Wenn ja, Datei Laden ImageForm->Image1->Picture->LoadFromFile( AnsiString(DirectoryTreeView1->Directory)+PathDelim+ AnsiString(FileListView1->Selections[0]->SR.Name)); |
Polygamie
Wählen Sie in »Projekt | Dem Projekt hinzufügen« die »MainFrm.pas« des CLX Explorers. Danach erzeugen Sie durch ein »Projekt | Projektname aktualisieren« eine Headerdatei für die Delphi-Unit. Sie wird tatsächlich erst durch das Aktualisieren erzeugt, also verbietet sich ein Einbinden der Headerdatei, wenn das Projekt nicht mindestens ein Mal mit der Pascal-Datei kompiliert wurde.
Die erzeugte Headerdatei können Sie dann auch durch Klick auf »Datei | Neu | Weitere | Projektname | Form1« vererben. Dabei sollten Sie dem vererbten Formular einen anderen Namen, etwa »inheritedForm« geben. Fügen Sie dann einen weiteren Knopf (etwa mit der Caption »Browse«) in Ihr »ImageForm« ein und verwenden die vererbte »Unit2.h« (etwa durch Klick auf »Datei | Unit einbinden« oder [Alt]+[F11]).
Geben Sie für »Button2« als Event-Handler »inheritedForm->Show();« an. Hier ist Vorsicht angebracht: Binden Sie nicht versehentlich noch das Original-Pascal-Formular ein! Es funktioniert zwar und sieht meist sehr ähnlich aus, aber per Definition wird jede Änderung in der vererbten Klasse ignoriert.
Ihre Delphi-CLX-Anwendung ist jetzt in der Kylix-für-C++-Anwendung nutzbar. Inkludieren Sie einfach in der Datei mit »inheritedForm« (beispielsweise »Unit2 .cpp«) die Unit Ihres »ImageForm« (in der Regel »Unit1.h«) und setzen die »onSelectItem«-Eigenschaft des »FileListView1« des »inheritedForm« auf die in Listing 1 genannte Konstruktion.

Abbildung 3: Das Kylix für C++-Projekt zeigt den Imageviewer und den Dateibrowser, an dessen Delphi-Vergangenheit nichts mehr erinnert.
Fazit: Einfach bis komplex
Die CLX-Portabilität zeigt bei dieser ersten Version mit C++-Unterstützung ein paar Kinderkrankheiten. Die beginnen bei der Groß- und Kleinschreibung von Borland-eigenen Unitnamen, die unter Windows anders ist als in Linux (beispielsweise »SoapHTTPClient«), gehen weiter über die Einstellung des portablen SQL-Client-Datasets in Delphi 7 zugunsten des Simple-Datasets und enden bei der Notwendigkeit der Konvertierung von C++-Projektdateien.
Kylix 3 bedeutet jedoch nicht nur, dass vorhandene Delphi- und C++-Projekte auf Linux portierbar sind, sondern auch, dass die jeweils komplette Delphi- und C++-Entwicklungsumgebung gewissermaßen zum ersten Mal wirklich vereint ist. Beide Umgebungen erlauben Rapid Application Development (RAD), durch einfaches Zusammenklicken des Codes für das Benutzerinterface. Diese Lösung steht für Linux bereit. Es ist damit eine der ersten, vielleicht die erste C++-RAD für Linux überhaupt.
In der Portier-Praxis entsteht ein weiträumiger Eindruck: Im besten Fall ist die Arbeit eine änderungsarme CLX-Projektübernahme und innerhalb weniger Minuten oder Stunden geschehen. Das andere Extrem wächst sich zum Kraftakt mit einem enormen Bedarf an Zeit und Know-how bei der Umwandlung einiger ehemaliger VCL-Anwendungen aus, mit opulenter BDE-Datenbank-Anbindung, Windows-Messages und direkten Win32-API-Aufrufen.
Diesen Kraftakt erspart sich in der Regel, wer von Anfang an CLX-Anwendungen entwickelt – am besten auch unter der richtigen Plattform, nämlich Linux. Aber auch eine CLX-Entwicklung unter Windows ist bei Verzicht auf alle Windows-Eigenheiten durchaus zu einer kompromisslosen Portierung in der Lage. Wie auch immer: Um Schwierigkeiten bei größeren Vorhaben schnell zu erkennen, ist das periodische Portieren eines CLX-Projekts auf die jeweils andere Plattform, mindestens einmal pro Woche, zu empfehlen. (jk)
|
Infos |
|---|
|
[1] Migration von Delphi 5 VCL nach Kylix CLX: [http://bdn.borland.com/article/images/27534/migrating_delphi5.pdf] [2] Eine Case-Study zu einem Cross-Plattform-Projekt: [http://www.borland.com/products/case_studies/kylix_colliers.html] [3] Kylix-Downloads (Trial, Open Edition, Patches und Project Conversion Utility): [http://www.borland.com/products/downloads/download_kylix.html] [4] BDE- nach dbExpress-Konvertierung: [http://www.borland.com/products/white_papers/pdf/migrating_borland_ database_engine_applications_to_ dbexpress.pdf] |
|
Der |
|---|
|
Jochen Stärk ist technischer Systemberater bei der deutschen Borland GmbH mit den Schwerpunkten C++Builder und Kylix. |
|
Andere |
|---|
|
Kylix ist nicht das einzige Werkzeug zum Entwickeln von Code, der für mehrere Plattformen taugt. Beispielhaft seien hier zwei Lösungen erwähnt. Omnis Studio 3 von Raining Data ist eine integrierte, objektorientierte RAD-Umgebung für Mac, Windows, Solaris und Linux. Die Programme sind – vorausgesetzt sie verwenden keine plattformspezifischen Externals oder Systemaufrufe – portabel. Omnis Studio eignet sich primär zum Entwickeln von Frontends mit passenden Backends, die wiederum nativ oder per ODBC auf MySQL, Oracle, DB2 und so weiter zugreifen. Die Standard Edition kostet rund 290 Euro. [http://www.omnis.net/products/studio] Die IDE Revolution von Runtime Revolution verfolgt einen ähnlichen Ansatz. Die damit entwickelten Text-Processing-Anwendungen, Multimedia-, Grafik- und Internet-Applikationen, CGI- und Shellskripte und Datenbank-Frontends laufen auf Linux/Unix, Windows, Mac OS und Mac OS X. Die Protokollsprache kennt assoziative Arrays, reguläre Ausdrücke und HTTP, FTP, Sockets, ODBC und natives MySQL. Zugriff auf in anderen Sprachen geschriebenen Module ist vorgesehen. Aktuell ist die Version 1.1.1, die funktionalere 2.0 ist in der Betaphase, die eigentlich Ende 2002 beendet sein sollte. Die Small Business Edition kostet rund 300 US-$, ein Starter Kit ist kostenlos. [http://www.runrev.com] |






