Sign in Join
Wiki copytemporary

Multiplatform Programming Guide/de: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11Zurück zu den [[Additional information/de|Zusätzlichen Informationen]].\
22
33Diese Seite ist der Beginn einer Einführung die das Hauptaugenmerk auf die Erstellung von Multiplattformanwendungen mit Lazarus richtet. Es werden die notwendigen Vorkehrungen, ein Programm portabel zu halten und auch der Portierungsprozess eines bereits bestehenden Programms betrachtet. Ich lade den Leser dazu ein, diesen Artikel zu erweitern.
44
55## Einführung in die Multiplattform Programmierung
66
77### Welche Betriebssysteme sollen unterstützt werden?
88
99Um diese Frage zu beantworten, müssen sie ermitteln, wer ihre potentiellen Nutzer sind und wie ihr Programm genutzt werden soll. Die Antwort auf diese Frage hängt davon ab, wo sie ihre Programm einsetzen möchten.
1010
1111Zum Beispiel Europa: Wenn sie eine Desktop-Anwendung entwickeln, können sie entscheiden, dass es nur für Windows und OS X Sinn macht. OS X ist das populärste Unix der Welt und strömt auf Desktops, wohingegen Linux meist dort heraus gezögert wird. Bedenken sie die 100:10:1 Regel, die besagt, dass in jeder größeren Organisation oder Benutzergruppe es nicht ungewöhnlich ist, Windows, OS X und Linux Arbeitsplätze in eben jener Aufteilung zu finden.
1212
1313An anderen Orten wie beispielsweise Südamerika ist Windows größtenteils marktbeherrschend, wohingegen Linux als Dekstop Plattform aufstrebt und in einigen großen Marktketten fast gleich mit Windows verkauft wird. OS X wird hauptsächlich im Audio- und Videobereich eingesetzt.
1414
1515Ist die Hand voll OS X und Linux Nutzer den extra Portierungsaufwand wert, der zum Entwickeln, Packen, Verteilen und Supporten benötigt ist? Ein klares ja, wenn es das Projekt es verlangt. Oder wenn der mehr benötigte Aufwand gering ist, wird die Antwort ebenso wahrscheinlich ja sein. Wenn sie sie aus Prinzip unterstützen, wird die Antwort auch ja sein, solange der extra Aufwand nicht als Hinderungsgrund zur Fertigstellung des Projektes steht.
1616
1717Wenn sie Software entwickeln, die auf einem Webserver laufen soll, ist die am meisten genutzte Plattform Unix. In diesem Fall ist es sinnvoll, Linux, Solaris, *BSD und andere Unix-Derivate als Zielplattform anzusehen, wobei zum Teil auch Windows Server zum Einsatz kommen.
1818
1919Wenn sie nur für eine Plattform entwickeln, werden vielleicht Free Pascal und Lazarus nicht die besten Mittel dafür sein, es sei denn, sie möchten sich die Möglichkeit offen halten, spätere Versionen ihrer Software auf andere Plattformen zu portieren. Wenn sie beispielsweise nur Windows Desktopanwendungen erstellen, könnte Delphi die bessere Alternative sein.
2020
2121Sobald sie die Plattformunabhängigkeit gemeistert haben, können Sie sich normalerweise auf das Problem konzentrieren, für das die Software entworfen werden soll und die Hauptzeit der Entwicklung auf der Plattform verbringen, über die sie verfügen oder auf der sie sich am wohlsten fühlen. Sie können, sobald Sie die Fallstricke der Plattformunabhängigkeit in Ihrem Design erkannt haben, größtenteils die anderen Plattformen ignorieren, ebenso, als wenn sie für eine einzelne Plattform entwickeln würden.
2222
2323Jedoch kommen sie an einen Punkt, an dem sie die Verteilung und die Ausführung ihres Programms auf den anderen Plattformen testen müssen. Spätestens dann ist es hilfreich, unbegrenzten Zugriff auf Rechner mit ihren gewählten Zielplattformen zu haben.
2424
2525Wenn Sie nicht mehrere PC's haben möchten, können Sie ein Dual-Boot System mit Windows und Linux konfigurieren oder Windows und Linux auf ihrem Mac in einem Emulator wie Virtual PC oder iEmulator laufen lassen.
2626
2727## Der Portierungsvorgang zwischen Windows und Linux
2828
2929### Windows API Funktionen
3030
3131Viele Windows Programme nutzen extensiv die Windows API. In plattformübergreifenden Anwendungen können diese Funktionen nicht direkt benutzt werden, sondern müssen in eine Kompilerdirektive eingeschlossen werden, z.B. {\$IFDEF Win32}.
3232
3333Glücklicherweise werden die meist genutzten Windows API Funktionen zur Verwendung in der Unit LCLIntf implementiert. Diese Unit kann die Lösung für Programme sein, die sehr stark die Windows API verwenden, obwohl die beste Lösung der Austausch dieser Aufrufe durch plattformübergreifende Komponenten der LCL ist. Sie können beispielsweise alle Aufrufe von GDI Zeichenfunktionen durch das TCanvas Objekt ersetzen.
3434
3535### Dateisystemunterschiede
3636
3737Einer besonderen Beobachtung für die Portierung von Applikationen zwischen Linux und Windows bedarf das Dateisystem. Unter Windows sind Dateinamen beispielsweise nicht case-sensitiv, wohingegen sie es unter Unix-Plattformen sind. Dies kann der Grund für eine Menge nervenraubender Fehler sein. Daher sollte jede portable Anwendung konsistente Dateinamen verwenden.
3838
3939### Unix kennt kein "Programmverzeichnis"
4040
4141Eine Sorge, wenn man Anwendungen zwischen Linux und Windows portiert, ist das Dateisystem. Viele Programmierer sind gewöhnt, ExtractFilePath(ParamStr(0)) oder Application.ExeName aufzurufen um den Ort der ausführbaren Datei zu erhalten, und dann nach den notwendigen Dateien für die Programmausführung (Bilder, XML Dateien, Datenbankdateien, etc) zu suchen basierend auf dem Ort der ausführbaren Datei. Das ist falsch unter Linux. Die Zeichenkette bei ParamStr(0) kann nicht nur das Verzeichnis des executable enthalten, ebenso variiert es zwischen verschiedenen Shell-Programmen (sh, bash, etc).
4242
4343Sogar wenn Application.ExeName tatsächlich wüsste, wo die ausgeführte Datei sich befindet, könnte es sich immer noch um einen symbolischen Link handeln und nur das Verzeichnis des Links würde verwendet werden.
4444
4545Was kann man also machen? Unter Linux sollten Sie zwei verschiedene Orte verwenden, um Konfigurations- und Ressourcen-Dateien zu speichern:
4646
4747- Ressourcendateien (z.B. Bilder, Hilfedateien)
4848
4949Ein festgelegtes, bevorzugtes Verzeichnis für ausführbare und Ressourcendateien, das unveränderlich ist.
5050
5151Das kann zum Beispiel sein: /usr/share/app_name oder /opt/app_name
5252
5353Die meisten Programme werden ohne Administrator/Root-Rechte ausgeführt werden und nur Administrator/Root wird die Schreibrechte an dem für ein bestimmtes Programm definierten Verzeichnis besitzen. Schreiben Sie daher keine Daten in das Verzeichnis, sondern greifen Sie nur lesend darauf zu.
5454
5555- Konfigurationsdateien
5656
5757Sie können die Funktion [[doc:rtl/sysutils/getappconfigdir.html|GetAppConfigDir]] aus der Unit SysUtils verwenden, um einen geeigneten Ort zur Ablage der Konfigurationsdateien auf verschiedenen Systemen zu ermitteln. Diese Funktion besitzt den boolschen Parameter Global. Wenn dieser true ist, dann ist das zurückgegebene Verzeichnis ein "globales Verzeichnis", d.h. es betrifft alle Benutzer auf dem System. Wenn der Parameter Global false ist, dann ist das Verzeichnis spezifisch für den Benutzer, der es ausführt. Auf Systemen, die Mehrbenutzer-Umgebungen nicht unterstützen, kann es sich um ein und dasselbe Verzeichnis handeln.
5858
5959Es gibt auch [[doc:rtl/sysutils/getappconfigfile.html|GetAppConfigFile]], das einen geeigneten Namen für eine Anwendungs-Konfigurationsdatei zurückgibt. Diese Funktion benutzt denselben Parameter Global wie GetAppConfigDir. Zusätzlich kann dort der optionale Parameter SubDir verwendet werden, der ans Ende der Verzeichniskette ein eigenes Unterverzeichnis anfügt (SubDir ist per Voreinstellung False, d.h. GetAppConfigFile(true) ist dasselbe wie GetAppConfigFile(true, false).
6060
6161Auf einem GNU/Linux-System ergeben die Aufrufe von GetAppConfigDir und GetAppConfigFile folgende Resultate:
6262
63-` program MyProg;`\
64-` (...)`\
65-` `\
66-` GetAppConfigDir(`**`true`**`);           ==>   '/etc/MyProg/'`\
67-` GetAppConfigFile(`**`true`**`);          ==>   '/etc/MyProg.cfg'`\
68-` GetAppConfigFile(`**`true, true`**`);    ==>   '/etc/MyProg/MyProg.cfg'`\
69-` `\
70-` GetAppConfigDir(`**`false`**`);          ==>   '/home/user/.config/MyProg/'`\
71-` GetAppConfigFile(`**`false`**`);         ==>   '/home/user/.config/MyProg.cfg'`\
72-` GetAppConfigFile(`**`false, true`**`);   ==>   '/home/user/.config/MyProg/MyProg.cfg'`
63+``` pascal
64+ program MyProg;
65+ (...)
66+
67+ GetAppConfigDir(true); ==> '/etc/MyProg/'
68+ GetAppConfigFile(true); ==> '/etc/MyProg.cfg'
69+ GetAppConfigFile(true, true); ==> '/etc/MyProg/MyProg.cfg'
70+
71+ GetAppConfigDir(false); ==> '/home/user/.config/MyProg/'
72+ GetAppConfigFile(false); ==> '/home/user/.config/MyProg.cfg'
73+ GetAppConfigFile(false, true); ==> '/home/user/.config/MyProg/MyProg.cfg'
74+```
7375
7476Sie werden bemerken, dass globale Konfigurationseinstellungen im Verzeichnis /etc gespeichert werden und lokale Konfigurationseinstellungen in einem verborgenen Ordner im Home-Verzeichnis des Benutzers (Verzeichnise, deren Namen mit einem Punkt beginnen, sind in unter Linux versteckte Verzeichnisse). Sie können ein Verzeichnis an dem Ort erstellen, der von GetAppConfigDir geliefert wird, und die Konfigurationbsdateien dort ablegen.
7577
7678Anmerkung: Normalen Benutzern ist es nicht erlaubt in das /etc Verzeichnis zu schreiben. Nur Benutzer mit Administratorrechten dürfen das.
7779
7880Das folgende Beispiel illustriert die Ausgabe dieser Funktionen auf verschiedenen Systemen:
7981
8082``` pascal
8183program project1;
8284
8385{$mode objfpc}{$H+}
8486
8587uses
8688 SysUtils;
8789
8890begin
8991 WriteLn(GetAppConfigDir(True));
9092 WriteLn(GetAppConfigDir(False));
9193 WriteLn(GetAppConfigFile(True));
9294 WriteLn(GetAppConfigFile(False));
9395end.
9496```
9597
9698- Die Ausgabe unter Windows XP:
9799
98100 C:\Programas\teste
99101 C:\Documents and Settings\felipe\Configurações Locais\Dados de aplicativos\project2
100102 C:\Programas\teste\project2.cfg
101103 C:\Documents and Settings\felipe\Configurações Locais\Dados de aplicativos\project2\project2.cfg
102104
103105Es ist zu beachten, dass die Funktion das Verzeichnis für globale Anwendungsdaten unter Windows verwendet.
104106
105107Anmerkung: Die Verwendung von UPX stört die Verwendung von GetAppConfigDir und GetAppConfigFile Funktionen.
106108
107109### Storing data files für ihre Anwendungen
108110
109111Eine sehr häufige Frage ist, wo man Datendateien speichern soll, die eine Anwendung benötigen könnte wie Musik, Bilder, Datenbanken und andere. Dieser Abschnitt bietet eine besondere Lösung, bei der die Datendateien im selben Verzeichnis wie das executable gespeichert werden (oder jedem anderen darauf basierenden Verzeichnis, wie MyDirectory + 'data' + PathDelim + 'myfile.dat'), und unter Unix-Systemen wird es in einem Verzeichnis sein, das aus einer Konfigurationsdatei gelesen wurde. Wenn keine Konfigurationsdatei existiert oder diese keine Info enthält, dann wird eine Konstante ('/usr/share/myapp/') genutzt als Vorgabeverzeichnis.
110112
111113Der Konfigurationsdateipfad wird mit der GetAppConfigFile Funktion aus der Laufzeitbibliothek gefunden.
112114
113115Unterhalb ist eine vollständige Unit, die sie für ihre Anwendungen verwenden können.
114116
115117``` pascal
116118unit appsettings;
117119
118120interface
119121
120122{$ifdef fpc}
121123 {$mode delphi}{$H+}
122124{$endif}
123125
124126uses
125127{$IFDEF Win32}
126128 Windows,
127129{$ENDIF}
128130 Classes, SysUtils, Forms, IniFiles;
129131
130132type
131133
132134 { TConfigurations }
133135
134136 TConfigurations = class(TObject)
135137 private
136138 ConfigFilePath: string;
137139 public
138140 {other settings as fields here}
139141 MyDirectory: string;
140142 constructor Create;
141143 destructor Destroy; override;
142144 procedure ReadFromFile(Sender: TObject);
143145 procedure Save(Sender: TObject);
144146 end;
145147
146148var
147149 vConfigurations: TConfigurations;
148150
149151implementation
150152
151153const
152154 DefaultDirectory = '/usr/share/myapp/';
153155
154156 SectionGeneral = 'General';
155157 SectionUnix = 'UNIX';
156158
157159 IdentMyDirectory = 'MyDirectory';
158160
159161{ TConfigurations }
160162
161163constructor TConfigurations.Create;
162164begin
163165{$ifdef win32}
164166 ConfigFilePath := ExtractFilePath(Application.EXEName) + 'myapp.ini';
165167{$endif}
166168{$ifdef Unix}
167169 ConfigFilePath := GetAppConfigFile(False) + '.conf';
168170{$endif}
169171
170172 ReadFromFile(nil);
171173end;
172174
173175destructor TConfigurations.Destroy;
174176begin
175177 Save(nil);
176178
177179 inherited Destroy;
178180end;
179181
180182procedure TConfigurations.Save(Sender: TObject);
181183var
182184 MyFile: TIniFile;
183185begin
184186 MyFile := TIniFile.Create(ConfigFilePath);
185187 try
186188 MyFile.WriteString(SectionUnix, IdentMyDirectory, MyDirectory);
187189 finally
188190 MyFile.Free;
189191 end;
190192end;
191193
192194procedure TConfigurations.ReadFromFile(Sender: TObject);
193195var
194196 MyFile: TIniFile;
195197begin
196198 MyFile := TIniFile.Create(ConfigFilePath);
197199 try
198200{$ifdef Win32}
199201 MyDirectory := MyFile.ReadString(SectionUnix, IdentMyDirectory,
200202ExtractFilePath(Application.EXEName));
201203{$else}
202204 MyDirectory := MyFile.ReadString(SectionUnix, IdentMyDirectory,
203205DefaultDirectory);
204206{$endif}
205207 finally
206208 MyFile.Free;
207209 end;
208210end;
209211
210212initialization
211213
212214 vConfigurations := TConfigurations.Create;
213215
214216finalization
215217
216218 FreeAndNil(vConfigurations);
217219
218220end.
219221```
220222
221223und hier ein Beispielcode, wie man diese Unit verwendet:
222224
223225``` pascal
224226 bmp := TBitmap.Create
225227 try
226228 bmp.LoadFromFile(vConfigurations.MyDirectory + 'MyBitmap.bmp');
227229 finally
228230 bmp.Free;
229231 end;
230232```
231233
232234## Making do without Windows COM Automation
233235
234236With Windows, Automation is a powerful way not only of manipulating other programs remotely but also for allowing other programs to manipulate your program. With Delphi you can make your program both an Automation client and an Automation server, meaning it can both manipulate other programs and in turn be manipulated by other programs.
235237
236238Leider ist Automation nicht verfügbar unter OS X und Linux. Jedoch können sie einen Teil der Funktionalität von Automation unter OS X simulieren unter Verwendung von AppleScript.
237239
238240AppleScript ist ähnlich wie Automation in mancher Hinsicht. Zum Beispiel, sie können Skripte schreiben, die andere Programme manipulieren. Hier ist ein sehr einfaches Beispiel von AppleScript, das NeoOffice startet (die Mac Version von OpenOffice.org):
239241
240-` tell application "NeoOffice"`\
241-`   launch`\
242-` end tell`
242+``` pascal
243+ tell application "NeoOffice"
244+ launch
245+ end tell
246+```
243247
244248Eine Anwendung, die is designed to be manipulated by AppleScript provides a "dictionary" of classes and commands that can be used with the app, similar to the classes of a Windows Automation server. However, even apps like NeoOffice that don't provide a dictionary will still respond to the commands "launch", "activate" and "quit". AppleScript can be run from the OS X Script Editor or Finder or even converted to an app that you can drop on the dock just like any app. You can also run AppleScript from your program, as in this example:
245249
246250``` pascal
247251 Shell('myscript.applescript');
248252```
249253
250254Dies setzt voraus, dass das Skript in der angegebenen Datei ist. You can also run scripts on the fly from your app using the OS X OsaScript command:
251255
252256``` pascal
253257 Shell('osascript -e '#39'tell application "NeoOffice"'#39 +
254258 ' -e '#39'launch'#39' -e '#39'end tell'#39);
255259 {Note use of #39 to single-quote the parameters}
256260```
257261
258262However, these examples are just the equivalent of the following Open command:
259263
260264``` pascal
261265 Shell('open -a NeoOffice');
262266```
263267
264268Die wirkliche Stärke von AppleScript is to manipulate programs remotely to create and open documents and automate other activities. How much you can do with a program depends on how extensive its AppleScript dictionary is (if it has one). For example, Microsoft's Office X programs are not very useable with AppleScript, whereas the newer Office 2004 programs have completely rewritten AppleScript dictionaries that compare in many ways with what's available via the Windows Office Automation servers.
265269
266270While Linux shells support sophisticated command line scripting, the type of scripting is limited to what can be passed to a program on the command line. No access to a program's internal classes and commands are available with Linux the way they are via Windows Automation and OS X AppleScript.
267271
268272As with Windows, many OS X and Linux programs are made up of multiple library files (.dylib and .so extensions). Sometimes these libraries are designed so you can also use them in programs you write. While this can be a way of adding some of the functionality of an external program to your program, it's not really the same as running and manipulating the external program itself. Instead, your program is just linking to and using the external program's library similar to the way it would use any programming library.
269273
270274## Arbeiten mit Dateien und Ordnern
271275
272276Wenn sie mit Dateien und Ordnern arbeiten ist es wichtig, nicht-plattformspezifische Pfadbegrenzungszeichen und Zeilenendsequenzen zu verwenden. Hier ist eine Liste der deklarierten Konstanten in Lazarus, die bei der Arbeit mit Dateien und Ordnern verwendet werden sollten.
273277
274278- **PathSep**, **PathSeparator**: path separator when adding many paths together (';', ...)
275279- **PathDelim**, **DirectorySeparator**: directory separator for each platform ('/', '\\', ...)
276280- **LineEnding**: proper line ending character sequence (#13#10 - CRLF, \#10 - LF, ...)
277281
278282## Weiterführende Links
279283
280284- <http://www.midnightbeach.com/jon/pubs/Kylix.html> - Ein Führer für Windows-Programmierer, die mit Kylix beginnen möchten. Viele Konzepte und Code Beispiele gelten auch für Lazarus.
281285- <http://www.stack.nl/~marcov/porting.pdf> Ein Handbuch für das Schreiben von portablem Quellcode, hauptsächlich zwischen verschiedenen Compilern.
282286
283287---
284288*From the Free Pascal wiki, page "Multiplatform Programming Guide/de", as it stood on 2018-02-27 after a change by Mathias, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
285289Category: Deutsch
286290Category: Tutorials/de

Back to history