mardi 2 janvier 2001

Dll

DLL

Les dll (dynamic link library) sont très répandues dans la programmation Windows. Une dll est en fait une portion de code exécutable d'un fichier ayant une extension dll. N'importe quel programme peut faire appel à une dll.

Avantage d'une dll

  • Réutilisation du code
  • Partage du code entre plusieurs applications
  • Fractionnement du code
  • Meilleure gestion des ressources de Windows

Création d'une dll

Allez dans le menu File, cliquer sur New..., choisisez Dll



Syntaxe d'une dll


library Calculer;
uses
  SysUtils,
  Classes;
var //déclaration des variables
  TPS: double;
  TVQ: double;
  
//déclaration de la fonction
function CalculerTotal(Somme:double):double;register;
begin
  Somme := Somme * TPS + Somme;
  Somme := Somme * TVQ + Somme;
  Result := Somme;
end;

//exportation de la fonction afin de pourvoir l'utiliser dans les programmes
exports
  CalculerTotal;
  
//initialisation des variables
//peu pratique étant donné que la valeur des taxes peuvent changer
begin
  TPS:=0.07;
  TVQ:=0.065;
end.
Pour créer la dll, allez dans le menu project et cliquez sur build «nom du projet»

Portée d'une fonction ou procédure

Les fonctions et les procédures peuvent être locaux ou exportées à une dll.

Locale

Les fonctions et procédures locaux ne peuvent être utilisées qu'à l'intérieur de la dll. Il est imppossible d'y faire référence à l'extérieur de celle-ci donc aucun programme ne peut l'appeler.

Exporté

Les fonctions et procédures exportées peuvent être utilisées à l'extérieur de la dll. Les programmes peuvent appeler une telle fonction ou procédure.
Le code source ci-dessus utilisait une fonction exportée
Le mot Exports ainsi que le nom de la fonction doivent être inscrits
exports CalculerTotal;

Les deux types de fonction et procédure peuvent être utilisées simultanément dans une dll.

Chargement d'une dll

En delphi, il existe deux types de chargement pour une dll
  • Chargement statique
  • Chargement dynamique

Chargement statique

Lorsque l'application démarre la dll est automatiquement exécuté. Elle reste en mémoire tout au long de l'exécution du programme. Elle est simple d'utilisation. Il suffit d'ajouter le mot external à la procédure ou fonction afin de l'utiliser.

function CalculerTotal(Somme:double):double;register; external 'Calculer.dll';
Si la dll n'est pas trouvée, le programme ne pourra s'exécuter.

Code source disponible ici

Chargement dynamique

La dll est chargé en mémoire selon vos besoins. Sa mise en oeuvre est beaucoup plus complexe car vous devez charger et décharger la dll de la mémoire. La mémoire est utilisée plus adéquatement et l'application fonctionne plus rapidement. Il y a quelques règles que le programmeur doit suivre afin que tout fonctionne correctement.
  • Déclarer un type qui décrit la fonction ou la procédure
  • Charger la fonction ou procédure
  • Récupérer l'adresse de la fonction ou procédure
  • Appeler la fonction ou procédure
  • Décharger la fonction ou procédure

Déclarer un type qui décrit la fonction

TypeTCalculerTotal = function(Somme:double):double;

Charger la fonction ou procédure

dllInstance := loadlibrary('Calculer.dll');

Récurpérer l'adresse de la fonction

@CalculerTotal :=getprocaddress(dllInstance,'Calculerotal');

Appeler la fonction

Somme:=CalculerTotal(Somme);

Décharger la fonction

freelibrary(dllInstance);

L'allocation dynamique exige plus de travail, mais les ressources mémoires sont mieux gérées. 
Si on doit faire usage de la dll tout au long du programme, l'allocation statique est préférable. 

N'oubliez pas d'utiliser les block try except et try finally pour éviter les erreurs
Code source disponible ici

Méthode d'appel de fonction et procédure
Il existe quelques conventions pour appeler une fonction ou procédure. Comme vous avez pu remarquer dans la section chargement statique, j'ai utilisé le mot register pour appeler la fonction.

Sommaire des conventions d'appels


Directive Ordre de paramètre Utilité
register Gauche - Droite La plus efficace, évite des accès sur la pile
pascal Gauche - Droite Comptabilité antérieure
cdecl Droite - Gauche Utilisé pour les appels de dll écrite en c, c++
stdcall Droite - Gauche Appel pour les api Windows
safecall Droite - Gauche Appel pour les api Windows

Exportation de chaîne de caractère

Les dll créer à l'aide de Delphi peuvent être utilisé dans d'autre langage. Pour cette raison, on ne peut utiliser n'importe qu'elle type de donnée. Les types qui existe en Delphi n'existe pas nécessaire sous d'autre langage. Il est préférable d'utiliser des types de données natif de Linux ou Window. La dll pourra ainsi être utilisé par d'autre programmeur qui utilise d'autre langage que celui que nous utilisons.

Il est possible d'utiliser les strings et les dynamic array de Delphi dans une dll. Il faut inclure l'unité ShareMem dans la dll et le programme qui l'utilise. De plus cette unité devra être la première dans chaque fichier du projet. Il faut être certain que la dll sera utilisé que dans delphi sinon des problèmes surviendront.

Les strings telle que nous les connaissons n'existe pas en C, C++... nous utiliserons alors les PChar.

PChar

Les PChar ont leur premier caractère à l'indice zéro contrairement au string qui commmence à 1. Un PChar est une chaîne de tableau de caractère qui se termine par Nul (#0). Qui a dit C? Aussitôt que le caractère nul est trouvé c'est la fin de la chaîne.
Nous allons créer un exemple afin de montrer l'utilisation de string dans une dll. Le programme envoirera une string à la dll. Cette dll mélangera les caractères et retournera la string au programme.

Voici le code de la dll
library mixstr;

uses
  SysUtils,
  Classes;

{$R *.res}

Function MixToStr(StrText:PChar):Pchar;stdcall;
var
  i, j : Integer;
  c1   : Char;
Begin
  For i:=Length(StrText)-1 downto 0 Do
  Begin
    j:=Random(i)+1;
    c1:=StrText[i];
    StrText[i]:=StrText[j];
    StrText[j]:=c1;
  End;
  result := StrText;
End;

exports
  MixToStr;

begin
end.
Voici le code du programme
var
  Form1: TForm1;
  function MixToStr(str:PChar):PChar;stdcall; external 'mixstr.dll';

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
   edtRecu.Text := MixToStr(pchar(edtEnvoyer.Text));
end;
 

Code source disponible ici