Multiplatform Programming Guide/de

From Lazarus wiki
Jump to navigationJump to search

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) polski (pl) русский (ru) 中文(中国大陆)‎ (zh_CN)

Diese 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 Programmes betrachtet. Ich lade den Leser dazu ein, diesen Artikel zu erweitern.

Einführung in die Multiplattform Programmierung

Welche Betriebssysteme sollen abgedeckt werden?

Um 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.

For example, on Europe, if you're developing desktop software you may decide that it only makes sense to develop for Windows and OS X. OS X is the most popular Unix in the world and is surging on the desktop, whereas Linux has mostly stalled there. Remember the 100:10:1 rule, which says that in any large organization or group of users, it's not unusual to find Windows, Mac and Linux desktop computers in roughly these ratios.

On other places, like South America, Windows is mostly dominant, Linux is rising as a desktop platform, even outselling Windows on big supermarket networks, and Mac OS X is restricted to Video and Sound work.

Are the handful of users running OS X and Linux worth the extra effort that will be required to develop, package, distribute and support separate versions for them? Obviously if the project requires this, then the answer will be yes. Or if the amount of extra effort will be small, then the answer will probably be yes as well. If you want to support them out of principle, then the answer may also be yes as long as the extra effort doesn't get in the way of finishing the software.

Wenn 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.

Wenn 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.

Once you've mastered cross-platform development, you can usually just focus on the problem the software is designed to solve and do most of your development on whatever platform your have available or feel most comfortable with. That is, once you've addressed any cross-platform issues in your design, you can largely ignore the other platforms, much as you would when developing for a single platform. However, at some point you'll need to test deploying and running your program on the other platforms and it will be helpful to have unrestricted access to machines running the all target operating systems. If you don't want multiple physical boxes, you can look into configuring a dual-boot Windows-Linux box or running Windows and Linux on your Mac under an emulator like Virtual PC or iEmulator.

Der Portierungsvorgang zwischen Windows und Linux

Windows API Funktionen

Viele Windows Programme nutzen extensiv die Windows API. In plattformübergreifenden Applikationen können diese Funktionen nicht direkt benutzt werden, sondern müssen in eine Kompilerdirektive eingeschlossen werden, z.b. {$IFDEF Win32}.

Glü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 die Substitution dieser Aufrufe durch plattformübergreifende Komponenten der LCL ist. Sie können beispielsweise alle Aufrufe von GDI Zeichenfunktionen durch das TCanvas Objekt ersetzen.

Dateisystemunterscheide

A basic concern when porting application between Linux and Windows is the file system. To start with Windows filenames are not case sensitive, while they are on Unix platforms. This can be the cause of annoying bugs, so any portable application should use consistently filenames.

Linux kennt kein "Programmverzeichnis"

One concern when porting applications between Linux and Windows is the file system. Many programmers are used to call ExtractFilePath(ParamStr(0)) or Application.ExeName to get the location of the executable, and then search for the necessary files for the program execution (Images, XML files, database files, etc) based on the location of the executable. This is incorrect in Linux. The string on ParamStr(0) may not only not contain the directory of the executable, as it also varies between different shell programs (sh, bash, etc).

Even if Application.ExeName could in fact know the directory where the file under execution is, that file could be a symbolic link, so you would get the directory of the link instead.

So what should we do? On Linux you should use two different places to store configurations and resource files:

  • Resource files (i.e. images, help files)

A fixed privileged location for the executable and resource files which will not change.

This location can be something like: /usr/share/app_name or /opt/app_name

Most programs will be executed without root privileges and the fixed directory for a given application usually only available for the root user to write, so don't write on this directory. Only read information from it.

  • Configuration files

You can use the GetAppConfigDir function from SysUtils unit to get a suitable place to store configuration files on different system. The function has one parameter, called Global. If it is True then the directory returned is a global directory, i.e. valid for all users on the system. If the parameter Global is false, then the directory is specific for the user who is executing the program. On systems that do not support multi-user environments, these two directories may be the same.

There is also the GetAppConfigFile witch will return an appropriate name for an application configuration file.

Here is an example of the output of those functions on different systems:

program project1;

{$mode objfpc}{$H+}

uses
  SysUtils;

begin
  WriteLn(GetAppConfigDir(True));
  WriteLn(GetAppConfigDir(False));
  WriteLn(GetAppConfigFile(True));
  WriteLn(GetAppConfigFile(False));
end.

The output on a GNU/Linux system:

/etc
/home/felipe/project1
/etc/project1.cfg
/home/felipe/.project1

You can notice that glocal configuration files are stored on the /etc directory and local configurations are stored on a hidden folder on the user's home directory. Directories whose name begin with a dot (.) are hidden on Linux. You can create a directory on the location returned by GetAppConfigDir and then store configuration files there.

The output on Windows XP:

C:\Programas\teste
C:\Documents and Settings\felipe\Configurações Locais\Dados de aplicativos\project2
C:\Programas\teste\project2.cfg
C:\Documents and Settings\felipe\Configurações Locais\Dados de aplicativos\project2\project2.cfg

Notice that the function uses the directory where the application is to store global configurations on Windows.

Note: The use of UPX interferes with the use of the GetAppConfigDir and GetAppConfigFile functions.

Making do without Windows COM Automation

With 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.

Unfortunately, Automation isn't available on OS X and Linux. However, you can simulate some of the functionality of Automation on OS X using AppleScript.

AppleScript is similar to Automation in some ways. For example, you can write scripts that manipulate other programs. Here's a very simple example of AppleScript that starts NeoOffice (the Mac version of OpenOffice.org):

 tell application "NeoOffice"
   launch
 end tell

An app that 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:

 Shell('myscript.applescript');

This assumes the script is in the indicated file. You can also run scripts on the fly from your app using the OS X OsaScript command:

 Shell('osascript -e '#39'tell application "NeoOffice"'#39 +
       ' -e '#39'launch'#39' -e '#39'end tell'#39);
       {Note use of #39 to single-quote the parameters}

However, these examples are just the equivalent of the following Open command:

 Shell('open -a NeoOffice');

The real power of 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.

While 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.

As 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.

Weiterführende Links