Introduction
Le but de cet article n'est pas d'expliquer
ce qu'est .NET, il y a une présentation ici
par Microsoft, mais de présenter ce qu'il va être possible
de faire avec Delphi for .NET et ce que j'ai pu
tester. Avec Delphi 7, le compilateur en ligne de
commande (dccil) ainsi que les premières unités de ce qui
sera la VCL for .NET sont livrés. Il est donc dès à
présent possible de commencer à tâter le terrain de ce que
sera l'avenir de Delphi sur cette plateforme. Le produit
final dont le nom de code est Galileo sera disponible
courant 2003.
Le Hello World
Pour commencer un programme simple:
program HelloWorld;
{$APPTYPE CONSOLE}
begin
Writeln('Hello World in Delphi for .NET');
end. |

On compile le programme avec le compilateur
en ligne de commande dccil
qui va produire un exécutable contenant du code MSIL
(MicroSoft Intermediate Language) conforme comme on peut le
vérifier avec le programme peverify
livré avec le SDK .NET.
Mais à partir de cette preview, il est
aussi possible d'accéder au framework .NET. Voici une
application simple l'utilisant:
unit Main_frm;
interface
uses
System.Windows.Forms,
System.Drawing;
type
TfrmMain = class(Form)
private
btnOk: Button;
procedure
InitializeComponents;
public
constructor Create;
procedure btnOkClick(Sender:
TObject; E: EventArgs);
end;
implementation
{ TfrmMain }
procedure TfrmMain.btnOkClick(Sender: TObject; E: EventArgs);
begin
MessageBox.Show('Coucou', 'Delphi for .NET preview');
end;
constructor TfrmMain.Create;
begin
inherited Create;
InitializeComponents;
end;
procedure TfrmMain.InitializeComponents;
begin
btnOk := Button.Create;
btnOk.Parent := Self;
btnOk.Location := Point.Create(10,10);
btnOk.Size := Size.Create(200,25);
btnOk.Text := 'Coucou';
btnOk.add_Click(btnOkClick);
end;
end. |
program GUI;
uses
System.Windows.Forms,
Main_frm in 'Main_frm.pas';
begin
Application.Run(TfrmMain.Create);
end. |

Dans cet exemple, on crée à partir des
classes du framework .NET une application fenêtrée.
On déclare une classe dérivant de
System.Windows.Forms.Form avec un bouton (System.Windows.Forms.Button).
Dans le constructeur de la fiche on va initialiser notre
composant bouton (taille, position, texte, etc.) et on va
lui ajouter un gestionnaire d'événement avec la méthode
add_Click correspondant à l'événement Click. On remarque
ici la gestion par ressources de Delphi est quand même
beaucoup plus pratique qu'une initialisation par code... ;-)
On obtient donc une application fenêtrée
plutôt rapidement en utilisant seulement le framework .NET.
Il est donc plus simple avec .NET de créer de telles applications
qu'avec les API WIn32. On retrouve une programmation proche
de la VCL au niveau du système.
Si vous compilez avec l'option -V, les
informations de debuggage sont incluses et il est possible
d'utiliser le debugger de la CLR (Common Language Runtime) DbgCLR fournit avec le
Framework SDK (C:\Program Files\Microsoft.NET\FrameworkSDK\GuiDebug\DbgCLR.exe).

Menu Debug | Program To Debug, indiquez le
programme que vous venez de compiler avec l'option -V. Puis
ouvrez le fichier source Pascal que vous voulez debugger.
Posez un point d'arrêt (F9) à la ligne qui vous intéresse
et lancez le programme sous contrôle du debugger (F5). Le
programme s'arrêtera sur le point d'arrêt.

Vous pouvez alors faire du pas à pas (Step
Over, F10) ou du pas à pas approfondi (Step In, F11).
Les unités et le Framework .NET
La compilation des unités Delphi produit
maintenant un fichier .dcuil. A chaque fois que l'on fait un
uses dans un programme on a
besoin du fichier .dcuil associé. Cela signifie que dans
notre exemple, lorsque l'on fait uses
System.Windows.Forms; il faut le fichier
System.Windows.Forms.dcuil. Le compilateur dccil est livré avec ces fichiers dcuil pour l'ensemble
du framework .NET. Avec ces dcuil il existe des fichiers .dcua
qui représentent une description des assemblies contenues
dans le namespace du dcuil. Le compilateur examine le
fichier dcua pour savoir quel dcuil il doit recompiler quand
une assembly a changé.
Il est maintenant possible de créer des
namespaces pour les unités:
| unit
MyCompany.MyApplication.MyForm;
interface
implementation
end. |
Cette unité sera par exemple compilée en
MyCompany.MyApplication.MyForm.dcuil et on l'utilisera de la
façon suivante:
| program
MyApplication;
uses
MyCompany.MyApplication.MyForm;
begin
end. |
Il est possible et parfois nécessaire
de préfixer par le namespace entier certains identificateurs:
type
TfrmMain = class(Form)
private
lblName: System.Windows.Forms.Label;
procedure
InitializeComponents;
public
constructor Create;
end;
var
AType: System.Type;
|
Label et type étant des mots réservés du
langage Pascal, il est important de préciser le namespace
pour indiquer au compilateur que ce n'est pas l'utilisation
du mot réservé mais d'un type du framework .NET
Puisque les dcuil du framework .NET sont
livrés avec le compilateur vous avez à disposition des
milliers de classes prêtes à l'emploi et que je vous
invite à explorer. Vous avez la référence de ces classes ici:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/cpref_start.asp
Les exécutables produits par dccil s'exécutant
maintenant dans l'environnement managed de la CLR, la
libération des objets se fait automatiquement par le
Garbage Collector. En général, Il n'est donc plus
nécessaire d'appeler Free ou de définir un destructor.
Pour des questions de compatibilité du code existant, Free
est toujours défini et peut être appelé, mais la
libération mémoire de l'objet n'est pas assuré après cet appel.
Néanmoins, il est nécessaire de libérer dans les
destructors les ressources qui ne seraient pas managed,
c'est à dire non prise en compte par la CLR.
La classe TObject est maintenant aliasée sur
le System.Object du framework .NET ce qui permet d'avoir une
interaction plus homogène avec le reste du framework. De
même, les types de base du pascal vont correspondre aux
types de la CLR.
Les Class Helpers
La création d'un nouveau compilateur pour
l'environnement .NET a permis d'introduire des nouveautés
dans le langage. L'une des plus puissante qui m'a été
donné de voir est celle des class helpers. Cette technique
a été ajouté pour répondre à la problématique de
compatibilité entre la VCL Win32 et le framework .NET. La
classe TObject, ancêtre de toutes classes en Delphi est
maintenant définie comme étant la classe System.Object de
.NET. Or la classe .NET ne possède pas les méthodes du
TObject que l'on avait avec la version Win32. Pour pallier
ce manque, Borland a crée une construction que l'on
appelle Class Helper permettant d'élargir la portée d'une
classe avec les méthodes définies dans le class helper.
Voyons cela sur un exemple concret:
program ClassHelperExample;
{$APPTYPE CONSOLE}
type
TMyClass = class(TObject)
public
procedure AMethod;
end;
TMyClassHelper = class helper for TMyCLass
procedure
AClassHelperMethod;
end;
{ TMyClass }
procedure TMyClass.AMethod;
begin
Writeln('TMyClass.AMethod');
end;
{ TMyClassHelper }
procedure TMyClassHelper.AClassHelperMethod;
begin
Writeln('TMyClassHelper.AClassHelperMethod');
end;
var
MyClass: TMyClass;
begin
MyClass := TMyClass.Create;
MyClass.AMethod;
MyClass.AClassHelperMethod;
end. |
On déclare tout d'abord, une classe TMyClass
avec une méthode AMethod.
Puis on déclare un class helper TMyClassHelper
pour la classe TMyClass.
Dans ce class helper on déclare une méthode AClassHelperMethod.
On implémente cette dernière comme faisant partie de la
classe TMyClassHelper, mais
en réalité elle va pouvoir être appelée à partir d'une
instance de TMyClass comme
on le voit dans le programme principal.
Voyons alors, avec ce mécanisme, ce
que donne l'implémentation de TObject pour Delphi for .NET:
type
TObject = System.Object;
TObjectHelper = class helper for TObject
procedure Free;
class function ClassType: TClass;
class function ClassName:
string;
class function ClassNameIs(const Name:
string): Boolean;
class function ClassParent: TClass;
class function ClassInfo: TObject;
class function InheritsFrom(AClass: TClass): Boolean;
class function MethodAddress(const Name:
string): TObject;
function FieldAddress(const Name:
string): TObject;
procedure Dispatch(var Message:
TObject);
procedure DefaultHandler(var Message:
TObject);
end; |
TObject bénéficie ainsi de toutes les
méthodes définies dans System.Object du framework .NET plus
les méthodes définies dans le class helper. Bien sûr,
toutes les classes descendantes de TObject en bénéficie
aussi.
Il est aussi possible d'hériter d'un autre
helper class.
TAnotherClassHelper =
class helper(TMyClassHelper) for TMyCLass
procedure AnotherClassHelperMethod;
end; |
Nous avons vu le principe de base des class
helpers, à vous maintenant d'explorer les comportements en
essayant différentes combinaisons sur des exemples comme
ci-dessus.
Les nouveautés du langage
Comme l'environnement d'exécution qu'est
.NET demande un code dit safe, certaines constructions
deviennent non valides et obsolètes pour Delphi for .NET
comme les pointeurs et tout ce qui se rapporte directement
à la mémoire, les allocations de mémoire (GetMem, FreeMem,
ReallocMem) les fichiers typés, les transtypages dans
des types incompatibles, etc. Delphi 7 intègre des
avertissements quant à la nature safe du code que vous
compilez pour Win32. Ces avertissements peuvent être
activés pour tester la qualité de votre code en vue
d'être porté vers .NET.
En plus des class helpers que l'on a vu
précédemment, Delphi for .NET intégrera d'autres
nouveautés, qui sont pour l'instant encore en recherche. En
vrac on peut citer:
-
Les méthodes et classes finales (non
héritables)
-
Les types imbriqués (définir une
classe dans une autre)
-
Méthodes dans les records (mais non
virtuelles). Les records deviennent ainsi des objets
automatiques (sans allocation dynamique, mais sur la
pile)
-
Variables de classe (static)
-
Propriétés de classe (static)
-
Gestionnaire d'événements multiples (Include
et Exclude seront surchargés pour ajouter ou retirer un
gestionnaire)
-
Surcharge de propriétés (property
overload)
-
...
Conclusion
Le compilateur Delphi for .NET livré avec
Delphi 7 est une version que l'on pourrait encore qualifiée
d'alpha. Il reste beaucoup de choses à implémenter, mais
on peut déjà commencer à jouer avec et à utiliser les
classes du framework .NET ce qui est déjà énorme ! Cela
donne un bon avant goût de ce que sera Galileo courant 2003 et
on espère une compatibilité proche de la VCL pour migrer
facilement les applications vers cette nouvelle plateforme.
par Jean-Philippe
BEMPEL
|