Les librairies (dll) et les packages (bpl)
Définitions
Librairie : on appelle librairie un fichier binaire mettant à disposition un ensemble de routines appelables de l’extérieur par d’autres programmes. Dans le système d’exploitation Windows, le type de fichier privilégié de librairie sont les fichiers .dll. dll signifie Dynamic Link Library. Il existe différents types d’appels qui sont standardisés. De ce fait, un programme extérieur répondant aux exigences du format d’appel peut utiliser une dll fournie par un tiers, même si les deux programmes ne sont pas écrits dans le même langage.
Ainsi, on peut avoir une dll écrite en C qui correspond à un driver de carte et un programme écrit en Delphi exploitant ce driver. Le point important étant que le programme écrit en Delphi respecte les conventions d’appel des routines exportées de la dll.
Les conventions d’appel les plus utilisées sont :
-
cd ...
Mise en pratique de l’utilisation d’une dll
1. Création
Pour créer une dll, utilisons le Wizard de RAD Studio. Faisons File - New - Other et choisissons Bibliothèque dynamique.
L’IDE génère un nouveau projet. Faire un Save all en renommant le projet en DllExemple.
On obtient le dpr suivant :
library DllExemple;
uses
System.SysUtils,
System.Classes;
{$R *.res}
begin
end.
Le mot réservé library indique que le résultat de la compilation sera une dll.
2. Export de routines
Pour l’exemple, écrivons deux routines simples qui permettent de faire une addition et une multiplication.
Ajoutons une unité au projet ’Calcul.pas’.
Déclarons deux routines AddNumber et MulNumber en définissant la convention d’appel à stdcall.
unit Calcul;
interface
function AddNumber(const a, b: double): double;stdcall;
function MulNumber(const a, b: double): double;stdcall;
implementation
function AddNumber(const a, b: double): double;stdcall;
begin
Result := a + b;
end;
function MulNumber(const a, b: double): double;stdcall;
begin
Result := a * b;
end;
end.
On remarque l’écriture de la convention d’appel stdcall dans la déclaration de la fonction. Pour l’instant, les routines ne sont pas exploitables de l’extérieur.
Il faut utiliser le mot-clé exports. Plaçons la liste des routines à exporter dans le dpr.
Le dpr devient :
library DllExemple;
uses
System.SysUtils,
System.Classes,
Calcul in 'Calcul.pas';
{$R *.res}
exports
AddNumber,
MulNumber;
begin
end.
Dans les cas d’utilisations standards de dll, il faut se contenter de ne passer que des types primitifs en paramètre d’appel des routines. Les pointeurs non typés peuvent aussi transiter. Pour rappel, les types primitifs sont les booléens, les entiers et les nombres décimaux. La taille de ces types est toujours connue à l’avance. Un type integer a une taille de 4 octets et un type double 8 octets.
3. Exploitation d’une...
Les packages BPL Delphi
Delphi propose deux types de packages : des packages ’runtime’, utilisés lors de l’exécution d’un programme, ou des packages ’design’ de conception, utilisés lors de la création d’un programme avec l’IDE. Il faut savoir que l’IDE Delphi embarque ce genre de package design et les interfaces pour proposer les contrôles et les composants dans sa palette.
1. Création d’un package runtime
L’intérêt d’un package Delphi, à l’instar d’une assembly C#, est que l’on peut échanger n’importe quel type de donnée, à savoir des objets complexes.
Ainsi, on peut concevoir un package comme un regroupement de routines ou de classes pouvant être utilisées par différents binaires d’une solution logicielle.
Utilisons le Wizard de projet de Delphi. File - New - Other et choisissons Package.
Examinons la source de projet généré :
package BplCustom;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO OFF}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
rtl;
end.
Le mot réservé package définit le type de binaire (BPL) qui va être généré.
On voit apparaître une nouvelle directive requires.
En effet, les packages peuvent avoir des dépendances avec d’autres packages. On peut décider comme on l’a vu précédemment avec les dll de lier les packages statiquement...
Conclusion
Dans ce chapitre ont été abordées l’élaboration et l’utilisation de bibliothèques de routines ou de composants faites en Delphi ou non.
Le fait de rendre accessible des morceaux de code dans des bibliothèques est une chose très courante lors de l’élaboration de suites logicielles complexes où du code ’métier’ est partagé entre plusieurs applications.
La création de dll est aussi un bon moyen d’encapsuler des composants existant dans un langage et pas dans un autre. Cela permet de réutiliser du code éprouvé sans avoir besoin de le réécrire dans un autre langage.