Difference between revisions of "Multiplatform Programming Guide/fr"

From Lazarus wiki
Jump to navigationJump to search
Line 21: Line 21:
 
Une fois vous avez maitrisé le développement à travers les plates-formes, vous pourrez normalement vous concentrer sur le problème que le logiciel est destiné à résoudre  et faites votre développement sur le plate-forme disponible ou celui que vous vous sentez à l'aide en l'utilisant. Ainsi, Une fois que vous avez adressé des questions à travers les plates-formes dans votre conception, vous pouvez ignorer les autres, comme si vous développez pour un unique plate-forme. Cependant, à un moment vous aurez besoin de tester le déploiement et le fonctionnement de votre programme sur les autres plates-formes et il sera utile d'avoir un accès illimité à des machines qui utilisent les systèmes d'exploitations ciblés. Si vous voulez pas plusieurs boites physiques, vous pouvez configurer une boite à double boot Windows-linux ou exécutez Windows et de Linux sur votre Mac dans le cadre d'un émulateur comme Virtual PC ou iEmulator.
 
Une fois vous avez maitrisé le développement à travers les plates-formes, vous pourrez normalement vous concentrer sur le problème que le logiciel est destiné à résoudre  et faites votre développement sur le plate-forme disponible ou celui que vous vous sentez à l'aide en l'utilisant. Ainsi, Une fois que vous avez adressé des questions à travers les plates-formes dans votre conception, vous pouvez ignorer les autres, comme si vous développez pour un unique plate-forme. Cependant, à un moment vous aurez besoin de tester le déploiement et le fonctionnement de votre programme sur les autres plates-formes et il sera utile d'avoir un accès illimité à des machines qui utilisent les systèmes d'exploitations ciblés. Si vous voulez pas plusieurs boites physiques, vous pouvez configurer une boite à double boot Windows-linux ou exécutez Windows et de Linux sur votre Mac dans le cadre d'un émulateur comme Virtual PC ou iEmulator.
  
== Programmation multi-pateforme ==
+
== Programmation multi-plateforme ==
  
 
=== Travailler avec les fichiers et les dossiers ===
 
=== Travailler avec les fichiers et les dossiers ===

Revision as of 18:28, 3 July 2010

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

Cette page est le début d'un tutoriel qui concerne l'écriture d'applications multiplatforme sur Lazarus. Il couvrira les précautions nécessaires pour s'assurer qu'un programme peut être facilement porté et le processus pour porter un programme déjà existant. Je vous invite pour m'aider à améliorer l'article.

Introduction à la programmation multi-plateformes

De combien de boîtes avez-vous besoin?

Pour répondre à cette question, vous devez d'abord déterminer qui sont vos utilisateurs et comment votre programme va être utilisé. Cette question dépend de l'endroit où vous déployez votre application.

Si vous développez des logiciels générique du bureau, Windows est évidement le plateforme le plus important, mais l'inclue des versions pour Mac OS X et linux peut être parfois la différence que fera de votre logiciel choisi au lieu d'un autre qui supporte pas les autres plateforme.

La valeur exacte des différents systèmes d'exploitations varie beaucoup selon le pays, le type du logiciel, ainsi que les personnes que vous destinez par votre application, ainsi, on peut pas définir des règles générales. un petit exemple pour cela que Mac OS X est très populaire en Europe de l'ouest, cependant, en Amérique de Sud, il est surtout limité aux utilisation liées au vidéos et sons.

Dans plusieurs contrats de projets, une seule plate-forme est pertinente, et ceci n'est pas un problème. Free Pascal et Lazarus sont tout à fait capable d'écrire des logiciels destinés à une plate-forme spécifique. Vous pouvez, par exemple, accéder à toute l'API Windows pour écrire un logiciel bien intégré de Windows.

si vous êtes en train de développez un logiciel qui va être utilisé sur un serveur web, le plate-forme le plus utilisé est UNIX, pour tous les goûts. Dans ce cas, peut-être que seul linux, Solaris, *BSD et d'autres systèmes UNIX sont logiquement votre plate-forme cible. vous pourrez ajouter aussi un support pour Windows NT.

Une fois vous avez maitrisé le développement à travers les plates-formes, vous pourrez normalement vous concentrer sur le problème que le logiciel est destiné à résoudre et faites votre développement sur le plate-forme disponible ou celui que vous vous sentez à l'aide en l'utilisant. Ainsi, Une fois que vous avez adressé des questions à travers les plates-formes dans votre conception, vous pouvez ignorer les autres, comme si vous développez pour un unique plate-forme. Cependant, à un moment vous aurez besoin de tester le déploiement et le fonctionnement de votre programme sur les autres plates-formes et il sera utile d'avoir un accès illimité à des machines qui utilisent les systèmes d'exploitations ciblés. Si vous voulez pas plusieurs boites physiques, vous pouvez configurer une boite à double boot Windows-linux ou exécutez Windows et de Linux sur votre Mac dans le cadre d'un émulateur comme Virtual PC ou iEmulator.

Programmation multi-plateforme

Travailler avec les fichiers et les dossiers

Lorsqu'on travaille avec les fichiers et les dossiers, c'est important d'utiliser une plate-forme qui ne limite pas le chemin et les séquences de fin de ligne. Ici est une liste des constantes déclarées dans Lazarus pour être utilisé en travaillant avec les fichiers et les dossiers.

  • PathSep, PathSeparator:séparateur de chemin lors de l'ajout de nombreux chemins en même temps (';', ...)
  • PathDelim, DirectorySeparator: séparateur de répertoire pour chaque plate-forme ('/', '\', ...)
  • LineEnding: propre fin de ligne pour séquence de caractères (#13#10 - CRLF, #10 - LF, ...)

Une autre chose importante à noter la sensibilité de case des fichiers systèmes. Dans windows, les noms des fichiers ne sont pas à case sensible, cependant, elles le sont pour les plate-formes Unix. Cela peut être la cause de bugs ennuyeux, de sorte que toute application portable doit utiliser toujours les noms de fichiers.

Fichiers de configuration

vous pouvez utiliser la fonction 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.

IL y a aussi le GetAppConfigFile qui retournera un nom approprié pour un fichier de configuration d'application. Vous pouvez l'utiliser comme ça:

ConfigFilePath := GetAppConfigFile(False) + '.conf';

Dessous sont des exemples de la sortie de chemin d'accès par défaut des fonctions sur des différents systèmes:

program project1;

{$mode objfpc}{$H+}

uses
  SysUtils;

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

La sortie dans un systeme GNU/Linux:

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

Vous 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à.

La sortie de Windows XP:

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

Notez que la fonction a recours au répertoire où la fonction stockera la configuration global dans windows.

La sortie de wondows 98:

C:\Programas\PROJECT1
C:\Windows\Configurações Locais\Dados de aplicativos\PROJECT1
C:\Programas\teste\PROJECT1.cfg
C:\Windows\Configurações Locais\Dados de aplicativos\PROJECT1\PROJECT1.cfg

La sortie dans Mac OS X:

/etc
/Users/philhess/.config/testfelipe1
/etc/testfelipe1.cfg
/Users/philhess/.config/testfelipe1.cfg

Note: Le recours à des UPX interfère avec l'usage des fonctions GetAppConfigDir et GetAppConfigFile.

Note: 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.

Les données et les fichiers de ressources

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

Dans la plupart des unix (comme Linux, BSDs, solaris, etc) , les informations peut être une chose comme: /usr/share/app_name or /opt/app_name

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

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

Example

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

The configuration file path is located with the GetAppConfigFile function from the Free Pascal Runtime Library.

Below is a full unit which you can use at your applications.

unit appsettings;

interface

{$ifdef fpc}
  {$mode delphi}{$H+}
{$endif}

uses
{$IFDEF Win32}
  Windows,
{$ENDIF}
  Classes, SysUtils, Forms, IniFiles, constants;

type

 { TConfigurations }

 TConfigurations = class(TObject)
 private
   ConfigFilePath: string;
 public
   {other settings as fields here}
   MyDirectory: string;
   constructor Create;
   destructor Destroy; override;
   procedure ReadFromFile(Sender: TObject);
   procedure Save(Sender: TObject);
 end;


var
 vConfigurations: TConfigurations;

implementation

const
  DefaultDirectory = '/usr/share/myapp/';

  SectionGeneral = 'General';
  SectionUnix = 'UNIX';

  IdentMyDirectory = 'MyDirectory';

{ TConfigurations }

constructor TConfigurations.Create;
begin
{$ifdef win32}
 ConfigFilePath := ExtractFilePath(Application.EXEName) + 'myapp.ini';
{$endif}
{$ifdef Unix}
 ConfigFilePath := GetAppConfigFile(False) + '.conf';
{$endif}

 ReadFromFile(nil);
end;

destructor TConfigurations.Destroy;
begin
 Save(nil);

 inherited Destroy;
end;

procedure TConfigurations.Save(Sender: TObject);
var
 MyFile: TIniFile;
begin
 MyFile := TIniFile.Create(ConfigFilePath);
 try
   MyFile.WriteString(SectionUnix, IdentMyDirectory, MyDirectory);
 finally
   MyFile.Free;
 end;
end;

procedure TConfigurations.ReadFromFile(Sender: TObject);
var
 MyFile: TIniFile;
begin
 MyFile := TIniFile.Create(ConfigFilePath);
 try
  // Here you can read other information from the config file

{$ifdef Win32}
   MyDirectory := MyFile.ReadString(SectionUnix, IdentMyDirectory,
ExtractFilePath(Application.EXEName));
{$else}
   MyDirectory := MyFile.ReadString(SectionUnix, IdentMyDirectory,
DefaultDirectory);
{$endif}
 finally
   MyFile.Free;
 end;
end;

initialization

 vConfigurations := TConfigurations.Create;

finalization

 FreeAndNil(vTranslations);

end.

and here example code of how to use that unit:

  bmp := TBitmap.Create
  try
    bmp.LoadFromFile(vConfigurations.MyDirectory + 'MyBitmap.bmp');
  finally
    bmp.Free;
  end;

Windows specific issues

Windows API Functions

Many 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} ).

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

On Unix there is no "application directory"

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

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

To avoid this read the sections about configuration files and data files.

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

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.

See Also