Sign in Join
Wiki copytemporary

Multiplatform Programming Guide/fr: what changed

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

OldNewLine
11Cette page est le début d'un tutoriel sur l'écriture d'applications multiplatforme sur Lazarus. Il traitera des précautions à prendre pour qu'un programme puisse être facilement portable et de la façon de porter un programme déjà existant. Je vous invite à m'aider pour améliorer cet article.
22
33## Introduction à la programmation multi-plateformes
44
55### De combien de machines avez-vous besoin?
66
77Pour répondre à cette question, vous devez d'abord déterminer qui seront vos utilisateurs et comment votre programme va être utilisé. Cette question dépend de l'endroit où vous déployez votre application.
88
99Si vous développez des logiciels de bureautique, Windows est évidement la plateforme la plus importante, mais le fait d'inclure des versions pour Mac OS X et Linux peut parfois faire que votre logiciel sera choisi à la place d'un autre limité à une seule plateforme.
1010
1111Le succès des différents systèmes d'exploitation varie beaucoup selon le pays, le type de logiciel ainsi que selon les personnes à qui vous destinez votre application. On ne peut donc pas définir de règles générales. A titre d'exemple, Mac OS X est très populaire en Europe de l'ouest. Il est par contre essentiellement limité à la vidéo et à l'audio en Amérique de Sud.
1212
1313Dans beaucoup de projets, une seule plate-forme est pertinente et ce n'est pas un problème. Free Pascal et Lazarus sont tout à fait adaptés à l'écriture de logiciels destinés à une plateforme spécifique. Vous pouvez, par exemple, accéder à toute l'API de Windows pour écrire un logiciel bien intégré dans Windows.
1414
1515Si vous développez un logiciel qui va tourner dans un serveur web, la plateforme la plus utilisée sera une variantes d'UNIX. Dans ce cas, peut-être que seuls Linux, Solaris, *BSD et d'autres systèmes UNIX seront logiquement votre plateforme cible. Vous pourrez aussi ajouter le support de Windows NT.
1616
1717Une fois vous aurez maîtrisé le développement multi plateformes, vous pourrez normalement vous concentrer sur le problème que le logiciel doit résoudre et faire votre développement sur la plateforme à votre disposition ou sur celle où vous vous sentez le plus à l'aise. Ainsi, lorsque vous aurez réglé les problèmes de multi plateforme dans votre conception, vous pourrez ignorer les autres, comme si vous développiez pour une plateforme unique. Cependant, à un certain moment vous aurez besoin de tester le déploiement et le fonctionnement de votre programme sur les autres plateformes et il sera utile d'avoir un accès illimité à des machines qui utilisent les systèmes d'exploitation ciblés. Si vous ne voulez pas vous encombrer de plusieurs machines physiques, vous pouvez configurer un double boot Windows-Linux ou faire tourner Windows et Linux sur votre Mac dans une machine virtuelle comme Virtual PC, iEmulator ou VirtualBox.
1818
1919## Programmation multi-plateforme
2020
2121### Travailler avec les fichiers et les dossiers
2222
2323Lorsqu'on travaille avec les fichiers et les dossiers, il est important d'utiliser des séparateurs de chemin et des codes de fin de ligne indépendants de la plate-forme. Voici une liste de constantes prédéclarées dans Lazarus à utiliser lors du travail avec les fichiers et les dossiers.
2424
2525- **PathSep**, **PathSeparator** : séparateur de chemin lors de l'ajout de nombreux chemins en même temps (';', ...)
2626- **PathDelim**, **DirectorySeparator** : séparateur de répertoire pour chaque plate-forme ('/', '\\', ...)
2727- **LineEnding** : propre fin de ligne pour séquence de caractères (#13#10 - CRLF, \#10 - LF, ...)
2828
2929Autre chose importante à noter : la sensibilité à la casse des systèmes de fichiers. Dans Windows, les noms des fichiers ne sont pas sensible à la casse. Ils le sont en revanche sur les plateformes Unix. Cela peut être la cause de bugs ennuyeux. Il faut donc que toute application portable utilise des noms de fichiers cohérents.
3030
3131### Fichiers de configuration
3232
3333vous pouvez utiliser la fonction [[doc:rtl/sysutils/getappconfigdir.html|GetAppConfigDir]] de l'unité SysUtils pour obtenir un bon emplacement pour stocker les fichiers de configuration dans les différents systèmes. La fonction possède un seul paramètre, nommé Global. S'il est vrai, alors le répertoire retourné est un répertoire global, c'est à dire, valide pour tous les utilisateurs dans le système. Si le paramètre global est faux, alors, alors le répertoire est spécifique à l'utilisateur qui exécute le programme. Sur les systèmes qui ne prennent pas en charge les environnements multi-utilisateurs, ces deux répertoires peuvent être le même.
3434
3535IL y a aussi le [[doc:rtl/sysutils/getappconfigfile.html|GetAppConfigFile]] qui retournera un nom approprié pour un fichier de configuration d'application. Vous pouvez l'utiliser comme ça:
3636
3737ConfigFilePath := GetAppConfigFile(False) + '.conf';
3838
3939Dessous sont des exemples de la sortie de chemin d'accès par défaut des fonctions sur des différents systèmes:
4040
4141 program project1;
4242
4343 {$mode objfpc}{$H+}
4444
4545 uses
4646 SysUtils;
4747
4848 begin
4949 WriteLn(GetAppConfigDir(True));
5050 WriteLn(GetAppConfigDir(False));
5151 WriteLn(GetAppConfigFile(True));
5252 WriteLn(GetAppConfigFile(False));
5353 end.
5454
5555La sortie dans un systeme GNU/Linux:
5656
5757 /etc
5858 /home/felipe/project1
5959 /etc/project1.cfg
6060 /home/felipe/.project1
6161
6262Vous pouvez remarquer que les fichiers de configuration globale sont stockés dans le répertoire /etc et que les configuration locales sont stockés dans un dossier caché le répertoire d'accueil de l'utilisateur. Les répertoires dont le nom commence par un point (.) sont cachés dans Linux. Vous pouvez créer un répertoire dans l'emplacement retourné par GetAppConfigDir et ensuite stocker les fichiers de configuration là.
6363
6464La sortie de Windows XP:
6565
6666 C:\Programas\teste
6767 C:\Documents and Settings\felipe\Configurações Locais\Dados de aplicativos\project1
6868 C:\Programas\teste\project1.cfg
6969 C:\Documents and Settings\felipe\Configurações Locais\Dados de aplicativos\project1\project1.cfg
7070
7171Notez que la fonction a recours au répertoire où la fonction stockera la configuration global dans windows.
7272
7373La sortie de wondows 98:
7474
7575 C:\Programas\PROJECT1
7676 C:\Windows\Configurações Locais\Dados de aplicativos\PROJECT1
7777 C:\Programas\teste\PROJECT1.cfg
7878 C:\Windows\Configurações Locais\Dados de aplicativos\PROJECT1\PROJECT1.cfg
7979
8080La sortie dans Mac OS X:
8181
8282 /etc
8383 /Users/philhess/.config/testfelipe1
8484 /etc/testfelipe1.cfg
8585 /Users/philhess/.config/testfelipe1.cfg
8686
8787Note: Le recours à des UPX interfère avec l'usage des fonctions GetAppConfigDir et GetAppConfigFile.
8888
8989Note: Dans la plupart des cas les fichiers de configuration sont des fichiers de préférences,qui devraient être des fichiers XML avec l'extension ".plist" et être stockés dans le répertoire /Library/Preferences ou ~/Library/Preferences avec des noms tirés du champ "Bundle identifier" dans Info.plist du paquet d'application. L'utilisation de Carbon qui appele CFPreference... est probablement la façon la plus facile de faire cela. Les fichiers .config dans le répertoire User sont une violation des lignes du guide de programmation.
9090
9191### Les données et les fichiers de ressources
9292
9393Une question très commune est où stocker les fichiers de données que qu'une application pourrait avoir besoin, comme les images, musiques, les fichiers XML, les fichiers de base de donnée, les fichiers d'aide, ect... Malheureusement il n y a pas de fonction multi-plateforme pour avoir le meilleur emplacement afin de chercher un fichier de donnée. La solution est d'implémenter différemment dans chaque plateforme en utilisant les IFDEF. Dans Windows, tu peux supposer simplement que les fichiers sont dans le même chemin d'accès que l'exécutable, ou en position qui lui est relative.
9494
9595Dans la plupart des unix (comme Linux, BSDs, solaris, etc) , les informations peut être une chose comme: /usr/share/app_name or /opt/app_name
9696
9797La plupart des programmes seront exécutés sans les privilèges d'un administrateur, pour cela les programmes multi-plateformes doivent toujours sauvegarder les fichiers d'informations dans un endroit ayant l'accès en lecture, mais pas forcement un accès en écriture, et les fichiers de configuration dans un endroit avec les droits de lecture et écriture.
9898
9999Mac OS X is an exception among UNIXes. There the best way to deploy applications is using an application bundle, which includes all files your software will need. Then your resource files should be located inside the bundle, so it can be moved and continue working normally. You need to use CoreFoundation API calls to find the location of the bundle.
100100
101101#### Example
102102
103103This section presents a particular solution where under Windows the data files are stored on the same directory as the executable (or any other directory based on it, like MyDirectory + 'data' + PathDelim + 'myfile.dat'), and on Unixes it will be on a directory read from a configuration file. If no configuration file exists or it contains no info, then a constant ('/usr/share/myapp/') is utilized as the default directory.
104104
105105The configuration file path is located with the GetAppConfigFile function from the Free Pascal Runtime Library.
106106
107107Below is a full unit which you can use at your applications.
108108
109109 unit appsettings;
110110
111111 interface
112112
113113 {$ifdef fpc}
114114 {$mode delphi}{$H+}
115115 {$endif}
116116
117117 uses
118118 {$IFDEF Win32}
119119 Windows,
120120 {$ENDIF}
121121 Classes, SysUtils, Forms, IniFiles, constants;
122122
123123 type
124124
125125 { TConfigurations }
126126
127127 TConfigurations = class(TObject)
128128 private
129129 ConfigFilePath: string;
130130 public
131131 {other settings as fields here}
132132 MyDirectory: string;
133133 constructor Create;
134134 destructor Destroy; override;
135135 procedure ReadFromFile(Sender: TObject);
136136 procedure Save(Sender: TObject);
137137 end;
138138
139139 var
140140 vConfigurations: TConfigurations;
141141
142142 implementation
143143
144144 const
145145 DefaultDirectory = '/usr/share/myapp/';
146146
147147 SectionGeneral = 'General';
148148 SectionUnix = 'UNIX';
149149
150150 IdentMyDirectory = 'MyDirectory';
151151
152152 { TConfigurations }
153153
154154 constructor TConfigurations.Create;
155155 begin
156156 {$ifdef win32}
157157 ConfigFilePath := ExtractFilePath(Application.EXEName) + 'myapp.ini';
158158 {$endif}
159159 {$ifdef Unix}
160160 ConfigFilePath := GetAppConfigFile(False) + '.conf';
161161 {$endif}
162162
163163 ReadFromFile(nil);
164164 end;
165165
166166 destructor TConfigurations.Destroy;
167167 begin
168168 Save(nil);
169169
170170 inherited Destroy;
171171 end;
172172
173173 procedure TConfigurations.Save(Sender: TObject);
174174 var
175175 MyFile: TIniFile;
176176 begin
177177 MyFile := TIniFile.Create(ConfigFilePath);
178178 try
179179 MyFile.WriteString(SectionUnix, IdentMyDirectory, MyDirectory);
180180 finally
181181 MyFile.Free;
182182 end;
183183 end;
184184
185185 procedure TConfigurations.ReadFromFile(Sender: TObject);
186186 var
187187 MyFile: TIniFile;
188188 begin
189189 MyFile := TIniFile.Create(ConfigFilePath);
190190 try
191191 // Here you can read other information from the config file
192192
193193 {$ifdef Win32}
194194 MyDirectory := MyFile.ReadString(SectionUnix, IdentMyDirectory,
195195 ExtractFilePath(Application.EXEName));
196196 {$else}
197197 MyDirectory := MyFile.ReadString(SectionUnix, IdentMyDirectory,
198198 DefaultDirectory);
199199 {$endif}
200200 finally
201201 MyFile.Free;
202202 end;
203203 end;
204204
205205 initialization
206206
207207 vConfigurations := TConfigurations.Create;
208208
209209 finalization
210210
211211 FreeAndNil(vTranslations);
212212
213213 end.
214214
215215and here example code of how to use that unit:
216216
217217 bmp := TBitmap.Create
218218 try
219219 bmp.LoadFromFile(vConfigurations.MyDirectory + 'MyBitmap.bmp');
220220 finally
221221 bmp.Free;
222222 end;
223223
224224## Windows specific issues
225225
226226### Windows API Functions
227227
228228Many Windows programs use the Windows API extensively. On crossplatform applications those functions cannot appear, or must be enclosed by a condition compile (e.g. {\$IFDEF Win32} ).
229229
230230Fortunately many Windows API functions - the most often used - are implemented in a multiplatform way in the unit LCLIntf. This can be a solution for programs which rely heavily on the Windows API, although the best solution is to substitute these calls with true crossplatform components from the LCL. You can substitute calls to GDI painting functions with the TCanvas object, for example.
231231
232232### On Unix there is no "application directory"
233233
234234Many 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 wrong on unixes. The string on ParamStr(0) may contain a directory other then the one of the executable, and it also varies between different shell programs (sh, bash, etc).
235235
236236Even if Application.ExeName could in fact know the directory where the executable is, that file could be a symbolic link, so you would get the directory of the link instead.
237237
238238To avoid this read the sections about [[Multiplatform Programming Guide|configuration files]] and [[Multiplatform Programming Guide|data files]].
239239
240240## Making do without Windows COM Automation
241241
242242With 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.
243243
244244Unfortunately, Automation isn't available on OS X and Linux. However, you can simulate some of the functionality of Automation on OS X using AppleScript.
245245
246246AppleScript 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):
247247
248-` tell application "NeoOffice"`\
249-`   launch`\
250-` end tell`
248+``` pascal
249+ tell application "NeoOffice"
250+ launch
251+ end tell
252+```
251253
252254An 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:
253255
254-` Shell('myscript.applescript');`
256+```text
257+ Shell('myscript.applescript');
258+```
255259
256260This 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:
257261
258-` Shell('osascript -e '#39'tell application "NeoOffice"'#39 +`\
259-`       ' -e '#39'launch'#39' -e '#39'end tell'#39);`\
260-`       {Note use of #39 to single-quote the parameters}`
262+``` pascal
263+ Shell('osascript -e '#39'tell application "NeoOffice"'#39 +
264+ ' -e '#39'launch'#39' -e '#39'end tell'#39);
265+ {Note use of #39 to single-quote the parameters}
266+```
261267
262268However, these examples are just the equivalent of the following Open command:
263269
264-` Shell('open -a NeoOffice');`
270+```text
271+ Shell('open -a NeoOffice');
272+```
265273
266274The 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.
267275
268276While 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. There is no single, unified way to access a program's internal classes and commands with Linux the way they are via Windows Automation and OS X AppleScript. However, individual desktop environments (GNOME/KDE) and application frameworks often provide such methods of Interprocess Communication. On GNOME see Bonobo Components. KDE has the KParts framework, DCOP. OpenOffice has a platform neutral API for controlling the office remotely (google OpenOffice SDK) - though you would probably have to write glue code in another language that has bindings (such as Python) to use it. In addition, some applications have "server modes" activated by special command-line options that allow them to be controlled from another process. It is also possible (Borland did it with Kylix document browser) to "embed" one top-level X application window into another using XReparentWindow (I think).
269277
270278As 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.
271279
272280## See Also
273281
274282- <http://www.midnightbeach.com/jon/pubs/Kylix.html> A guide for Windows programmers starting with Kylix. Many of concepts / code snippets apply to Lazarus.
275283- <http://www.stack.nl/~marcov/porting.pdf> A guide for writing portable source code, mainly between different compilers.
276284
277285---
278286*From the Free Pascal wiki, page "Multiplatform Programming Guide/fr", as it stood on 2012-04-11 after a change by Milarepa, 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).*

Back to history