Vous êtes sur la page 1sur 25

Cration et utilisation de DLL avec Delphi

Date de publication : 12/08/05 , Date de mise jour : 19/08/05

Par Olivier Lance (olance.developpez.com)

Apprenez crer simplement des DLL avec Delphi ! Mes autres articles se trouvent sur Introduction I. Cration du projet
I-1. Cration du fichier I-2. "library" plutt que "program" I-3. L'avertissement de Borland

II. Premier exemple de DLL

II-1. Ce qu'il faut savoir II-2. Code minimal II-2-a. Compilation et inclusion de ressources II-2-b. Dclaration et implmentation de fonctions/procdures II-2-c. Exportation des fonctions II-3. Utiliser la DLL II-3-a. Mthode statique II-3-b. Mthode dynamique

III. Aller plus loin

III-1. Quand la liaison statique est suffisante III-1-a. La DLL III-1-b. Le programme III-2. Lorsque la liaison dynamique s'impose III-2-a. La (les) DLL III-2-b. Le programme

IV. Rflexes prendre, astuces, ...


IV-1. IV-2. IV-3. IV-4.

Conclusion Remerciements Rfrences

Partager des types entre application et DLL Veiller aux types de variables utiliss Les conventions d'appel Dboguer une DLL

Introduction
Une DLL, ou Dynamic Link Library, est un fichier contenant du code compil la manire d'un excutable. L'utilit est toutefois ici d'exporter les fonctions ou les procdures correspondant ce code, afin de les mettre disposition de toute application sachant les exploiter. Le but est ainsi de crer un code rutilisable par diffrents programmes, quels qu'ils soient. Delphi nous offre donc la possibilit de crer des DLL et d'en utiliser, qu'elles aient t programmes avec Delphi ou un autre langage. Nous allons donc tudier la procdure suivre pour crer et utiliser ces DLL, ainsi que certaines habitudes qu'il est bon de prendre pour assurer une ventuelle compatibilit avec des programmes qui ne seraient pas dvelopps avec Delphi.

I. Cration du projet

Projet DLL par dfaut

library Project1; { Remarque importante concernant la gestion de mmoire de DLL : ShareMem doit tre la premire unit de la clause USES de votre bibliothque ET de votre projet (slectionnez Projet-Voir source) si votre DLL exporte des procdures ou des fonctions qui passent des chanes en tant que paramtres ou rsultats de fonction. Cela s'applique toutes les chanes passes de et vers votre DLL --mme celles qui sont imbriques dans des enregistrements et classes. ShareMem est l'unit d'interface pour le gestionnaire de mmoire partage BORLNDMM.DLL, qui doit tre dploy avec vos DLL. Pour viter d'utiliser BORLNDMM.DLL, passez les informations de chanes avec des paramtres PChar ou ShortString. } uses SysUtils, Classes; {$R *.res} begin end.

I-1. Cration du fichier


La premire chose faire est de crer le projet qui permettra de compiler notre future DLL. Assurez-vous d'avoir bien enregistr/ferm tout projet en cours, puis partir du menu "Nouveau | Autre..." crez un nouveau projet de type "Expert DLL", disponible dans l'onglet "Nouveau".

Dans Delphi 2005, la procdure est la mme, si ce n'est que l'item "Expert DLL" se trouve dans le dossier "Proje La validation de la bote de dialogue vous ramnera l'diteur de Delphi qui contiendra la nouvelle unit cre, dont voici le contenu : Lorsqu'on le voit pour la premire fois, ce fichier peut tre droutant. C'est pourquoi nous allons nous attacher en dcrire les diffrences avec un projet d'application "classique".

I-2. "library" plutt que "program"


Tout d'abord il faut bien voir que le fichier gnr par Delphi n'est pas une unit ".pas", mais bien un fichier projet ".dpr". Cela ne signifie en aucun cas que vous ne pourrez pas utiliser d'units dans votre projet, mais que celles-ci ne sont pas ncessaires au premier abord : l'instar d'un programme en mode console, vous pouvez entrer tout le code de votre DLL dans le fichier du projet. A partir de cette remarque, une autre diffrence est aisment identifiable : l'habituel "program Project1;" a t remplac par "library Project1;". "library" est le mot rserv qui indiquera Delphi qu'il doit gnrer non pas un excutable mais une DLL. Vous pouvez vous-mme le vrifier en crant une nouvelle application puis en remplaant dans le fichier DPR le mot "program" par "library". A la compilation, le fichier verra son extension change de ".exe" ".dll".

I-3. L'avertissement de Borland


L'autre diffrence avec un fichier DPR d'application est le long commentaire ajout par Borland au dbut du fichier. Il donne quelques informations sur des prcautions prendre lors du dveloppement de DLL dans Delphi. En effet, le type string dans Delphi est un type particulier dont la gestion en mmoire diffre de la gestion des chanes de caractres par Windows. Ainsi Borland prvient que, si vous comptez faire transiter des variables de type string entre votre DLL et les applications qui l'utilisent, il vous faudra :

Ajouter 'ShareMem' en premire position dans la clause uses de votre DLL et des applications qui Dployer la DLL 'BORLNDMM.DLL' (Borland Memory Manager) avec votre propre DLL.
l'utiliseront Cette bibliothque de Borland remplace le gestionnaire de mmoire par dfaut de votre DLL dans le but de permettre l'change en mmoire de vos variables de type string.

Autant dire que ce n'est pas vraiment avantageux d'utiliser des string avec des DLL ! Cela limiterait d'ailleurs leur emploi des programmes incluant ShareMem, donc des programmes Delphi. Ce problme avec les string n'est pas le seul devoir tre relev, car les types de variables entre les langages ont souvent des caractristiques diffrentes. Tout cela sera discut dans la dernire partie de cet article.

II. Premier exemple de DLL

II-1. Ce qu'il faut savoir


Avant de commencer programmer une DLL, il serait judicieux, pour bien comprendre le code, de voir comment un fichier DLL est construit puis exploit au niveau de Windows. Nous ne donnerons pas les spcifications du format dans le dtail puisque ce n'est pas le but de cet article, mais seulement quelques points qui semblent importants pour saisir le code et les explications qui suivront.

Sur le site www.wotsit.org vous trouverez en recherchant le mot-clef "DLL" une srie de fichiers dcrivant le Comme bon nombre de fichiers, les DLL commencent par un entte donnant diverses informations sur le fichier, et la taille des donnes qui suivent. Celles-ci sont principalement, dans le cas du format PE, organises entables et en segments. Nous ne nous intresserons qu'aux tables des DLL, et principalement deux d'entre elles, dont une tout particulirement. La premire est plutt donne titre informatif, il s'agit de la table des ressources. Cette table liste toutes les ressources contenues dans les segments de donnes, renseignant leur nombre, le nom, la taille, le type de chacune etc.

Vous pouvez crer des DLL qui ne contiennent que des ressources de tout type, sans quelque forme de code qu fichier que Windows sera mme d'exploiter pour personnaliser vos diffrents dossiers et raccourcis. Voyez cet La seconde table intressante est la table des exportations. Comme dit plus haut, l'objectif d'une DLL est de fournir plusieurs applications une srie de fonctions ou de procdures. Ces dernires doivent donc tre accessibles qui sait les appeler, et pour cela elles sont exportes par l'intermdiaire de la table d'exportation. Cette table recense toutes les fonctions ou procdures exportes en fournissant leur

identifiant et l'adresse o les trouver dans la DLL. Les identifiants utiliss sont soit un nom sous forme d'une chane de caractres, soit un nombre unique au sein de la DLL.

La table d'exportations ne permet pas de retrouver les types des paramtres que demandent les fonctions ou Voyons maintenant comment sont agencs ces diffrents lments et, paralllement, comment Windows les utilise : En rgle gnrale, chaque excutable est li une ou plusieurs DLL, ne serait-ce que pour les appels l'API Windows. Une partie du code ncessaire aux applications est donc contenue dans diffrentes DLL, et un accs doit tre effectu chacune d'entre elles pour le bon fonctionnement du programme. Lorsqu'un excutable est lanc dans Windows, il est charg en mmoire par un PE-Loader. C'est par son intermdiaire que les liaisons avec les DLL seront effectues. Pour cela, le PE-Loader va charger les DLL ncessaires et, grce leur table d'exportations, retrouver toutes les fonctions ou procdures dont l'application a besoin. Il copiera en mmoire le code de ces routines de telle sorte que l'excutable pourra y accder au besoin, et lancera l'application. Ce fonctionnement implique trois "phases" distinctes dans la cration d'une DLL :

La compilation et l'inclusion de ressources ventuelles. La dclaration puis l'implmentation des fonctions et procdures de la DLL. La demande d'exportation de ces fonctions pour qu'elles soient mises disposition d'autres
applications. Nous allons immdiatement voir les solutions minimales pour raliser ces trois tapes.

II-2. Code minimal

II-2-a. Compilation et inclusion de ressources Cette premire tape n'est pas indispensable dans la ralisation d'une DLL. Qui plus est, la cration et l'inclusion de ressources dans un projet pourrait faire l'objet d'un tutoriel complet. C'est pourquoi nous ne dvelopperons pas cette partie. Vous pouvez vous rfrer cet article de DelphiCool si vous ne savez pas manipuler les ressources. Dans le code de la DLL, si vous souhaitez inclure un fichier de ressources que vous avez compil, ajoutez simplement la directive de compilation '{$R fichier_ressources.res}' pour que Delphi le prenne en compte lors de la compilation. Votre code ressemble donc ceci :

oncernant la gestion de mmoire de DLL .... }

res}

La compilation de ce code, si "fichier_ressources.res" existe dans le rpertoire de votre projet, vous donnera d'ores et dj une DLL valide mais... vide de code ! Nous allons donc maintenant voir comment lui donner une quelconque utilit.

II-2-b. Dclaration et implmentation de fonctions/procdures Notre premire DLL aura pour fonction de calculer la somme de deux nombres qui lui seront passs en paramtres, en appelant la fonction Somme. Rien de bien compliqu au niveau de l'implmentation, voici donc le nouveau code :

oncernant la gestion de mmoire de DLL .... }

teger): Integer; stdcall;

Il n'y a pas besoin de plus ! La fonction est implmente directement avant le "begin ... end.", sans dclaration prliminaire. Seule la convention d'appel "stdcall" est inhabituelle. Elle permet de spcifier la manire dont les paramtres sont envoys la fonction. Cette convention n'est pas la seule, mais est la plus courante. Ce point sera discut en dernire partie. Maintenant que la fonction est implmente, la DLL peut tre compile sans souci, mais la fonction ne sera toujours pas accessible par un programme extrieur. C'est le but de la dernire tape.

II-2-c. Exportation des fonctions Par rapport la complexit de l'organisation d'un fichier DLL pour ce qui est de l'exportation de fonctions, Borland a su faire quelque chose de simple ct code. Les fonctions exporter doivent tre signales dans une clause "exports", en prcisant ventuellement un nom identifiant la fonction grce "name" et/ou un indice pour cette fonction grce "index". Le nom et l'indice sont facultatifs, et des valeurs par dfaut pour chacun de ces deux paramtres sont attribues s'ils ne sont pas renseigns. Dans ce premier exemple, nous ne prciserons rien. Notre fonction sera donc exporte sous le nom 'Somme', avec un indice gal 1. Voici le code complet de notre DLL :

oncernant la gestion de mmoire de DLL .... }

teger): Integer; stdcall;

on, le nom d'exportation sera "Somme" et l'index 1

Attention, la clause exports ne peut pas tre utilise autrement que pour des p Il est impossible d'y mentionner des variables, classes ou autres objets.

Dans la suite de cet article, le fichier compil de cette DLL sera "DLL1.dll".

II-3. Utiliser la DLL


Notre DLL est maintenant prte tre utilise, il suffit de faire une petite application apte en appeler la fonction Somme. Crez un nouveau projet dans Delphi et crez une interface qui ressemble celle-ci :

Interface du programme Une fois cette interface cre, il faut lier notre application la DLL. Il y a pour cela deux mthodes : la mthode statique, la plus simple, et la mthode dynamique, plus complexe mais qui a galement son utilit. Nous utiliserons la mme interface pour les deux mthodes, seul le code changera.

II-3-a. Mthode statique La mthode de liaison statique est la plus simple mettre en place dans Delphi. Elle ne demande pas de programmation proprement parler, mais d'une simple dclaration pour chaque fonction ou procdure importer. Le principe est le suivant : vous fournissez Delphi les informations dont il a besoin pour lier votre programme la DLL, et il se charge lui-mme des oprations de liaison avec celle-ci. Ces oprations se passent au dmarrage de votre application, et apportent donc un inconvnient : si la DLL n'est pas prsente lors du lancement de l'application ou que la fonction demande n'est pas trouvable dans la DLL

donne, le programme plante et ne pourra tre excut. Il n'y a alors aucun moyen d'outrepasser le message d'erreur. Utilisez donc cette mthode en connaissance de cause et veillez ce que chaque DLL que vous utilisez soit bien dploye avec votre application. Les informations fournir Delphi pour importer votre fonction de la DLL sont les suivantes :

Le La Le Le

nom ou l'index de la fonction/procdure dans la DLL liste des paramtres, dans l'ordre, et le type de chacun type de retour s'il s'agit d'une fonction nom de la DLL o trouver la fonction/procdure

Il apparat vident qu'il faut parfaitement connatre la fonction que l'on veut utiliser pour pouvoir la lier au programme. Cette liaison se fait, comme annonc plus haut, au moyen d'une dclaration dans l'unit o vous souhaitez utiliser la fonction, dans la section "interface". Voici pour continuer notre exemple la dclaration de la fonction Somme importer de la DLL "DLL1.dll" :

rter

Integer): Integer; stdcall; external NomDLL;

Comme vous pouvez le constater cette dclaration ne diffre pas normment de celles dont vous devez avoir l'habitude. Nous retrouvons la convention d'appel "stdcall". Il est important qu'elle apparaisse dans la dclaration de la fonction, et surtout que la convention d'appel utilise soit identique entre la DLL et le programme, sans quoi les erreurs seront au rendez-vous. Le mot rserv qui suit, "external", prcde le nom de la DLL qui contient la fonction importer. L'utilisation de la constante NomDLL pour stocker le nom de la DLL permet une mise jour facile sir le fichier change de nom Aprs external nous aurions pu ajouter "name" ou "index", pour spcifier un nom ou un index particulier identifiant la fonction dans la DLL. Voici ce que cela aurait donn :

fiant le nom de la fonction teger): Integer; stdcall; external NomDLL name 'Somme';

iant son index teger): Integer; stdcall; external NomDLL index 0; Pour ce qui est de notre exemple, nous n'avons pas besoin de prciser quoi que ce soit. En effet, en l'absence de "name" ou de "index", Delphi utilise le nom de la fonction dclare dans notre code comme nom d'importation. Cela correspond ici "Somme", qui est bien le nom d'exportation de notre fonction dans la DLL. Si vous vouliez utiliser "Addition" pour nom de fonction dans le code de votre application, vous seriez alors oblig de spcifier "name 'Somme'" ou "index 0" dans votre dclaration. Maintenant que la fonction est dclare, Delphi saura o aller la chercher et il ne reste plus qu' l'utiliser comme toute autre fonction dans notre code. La seule chose que nous souhaitons est que le programme affiche la somme des termes A et B lorsqu'on clique sur le bouton "A + B = ?". Il s'agit donc d'appeler notre fonction dans l'vnement OnClick de ce bouton :

meClick(Sender: TObject);

%d = %d', [A.Value, B.Value, Somme(.Value, B.Value)]); Ce qui nous donne le rsultat escompt :

II-3-b. Mthode dynamique La mthode dynamique est plus complique mettre en place, du fait qu'il faille crire quelques lignes de code pour obtenir un lien valide vers la fonction dsire. Toutefois, cette mthode offre beaucoup plus de souplesse par rapport la gestion des erreurs, de la mmoire etc. En effet cette fois, nous allons grer nous-mmes l'intgralit du processus de liaison, au moyen principalement de deux API Windows : LoadLibrary etGetProcAddress. Pour pouvoir utiliser notre fonction, il faut procder en plusieurs tapes : Dans un premier temps, demander au systme de charger notre DLL en mmoire par l'intermdiaire de l'API LoadLibrary. Ensuite, si celle-ci est bien charge, on y rcupre l'adresse de notre fonction, grce l'APIGetProcAddress. Cette adresse nous la stockons dans une variable de type function ou procedure, dont les paramtres corrects ont t renseigns. La fonction s'utilise ensuite aussi facilement qu'une autre. Voici le code illustrant ces propos, toujours avec notre mme exemple de la fonction Somme :

LL: String; var HandleDLL: THandle; NomFct: String; IndexFct: Integer = -1): Pointer;

ar dfaut

L. On rcupre son handle ary(pAnsiChar(DLL));

chou, on sort

se de la fonction voulue, que l'on renvoie //Si l'index est ngatif on utilise le nom sous forme de chane dress(HandleDLL, pAnsiChar(NomFct))

l'index comme identifiant dress(HandleDLL, pAnsiChar(IndexFct));

meClick(Sender: TObject); //Pour stocker le handle de la DLL charge (A, B: LongInt): LongInt; stdcall; //Notre fonction, sous forme de variable

teur sur notre fonction nomme 'Somme' au sein de DLL1.dll ('DLL1.dll', HandleDLL, 'Somme');

u un pointeur valide sur une fonction en

ction se passe comme avec une fonction ordinaire + %d = %d', [A.Value, B.Value, Somme(.Value, B.Value)]);

rer la DLL lorsqu'elle n'est plus ncessaire LL); un message d'erreur : appeler Somme provoquerait une violation d'accs de chargement de la fonction "Somme"'); Afin de complter les commentaires du code, voici quelques explications : La fonction LierFonction est l pour charger la DLL en mmoire, puis rcuprer et renvoyer un pointeur sur la fonction qui nous intresse. L'ide est de pouvoir rutiliser cette fonction pour n'importe quel chargement de fonction/procdure dans une DLL. Voici la description des paramtres :

DLL : Le nom du fichier DLL charger. HandleDLL : Il s'agit d'une variable que l'appelant doit pouvoir rutiliser. A la sortie de la

fonction, elle contiendra soit la valeur 0 si le chargement a chou, soit le handle de la DLL dans le cas contraire. Ce Handle doit tre utilis pour librer la DLL. NomFct : Nom de la fonction charger. Il s'agit du nom d'exportation de la fonction qui nous intresse au sein de la DLL. IndexFct : Index de la fonction charger. Par dfaut -1, l'index ne sera utilis la place du nom que si sa valeur est donne. La procdure qui suit LierFonction n'est autre que l'vnement OnClick de notre bouton "A + B = ?". Deux variables y sont dclares. La premire, de type THandle, est l pour satisfaire au paramtre var "HandleDLL" deLierFonction. La seconde est plus inhabituelle : il s'agit d'une variable de type function, dont les paramtres et la convention d'appel sont dclars l'identique de notre fonction Somme dans DLL1.dll. Cette dclaration donne Delphi les informations dont il aura besoin lorsque nous appellerons la fonction, mais du ct de la mmoire, notre variable n'est qu'un simple pointeur sur une adresse qui contient le code de la fonction excuter. Ainsi, l'adresse de la fonction rcupre par GetProcAddress peut tre assigne notre variable, ce qui nous permet d'utiliser la fonction exporte de la DLL comme nous l'aurions fait avec toute autre fonction. Lorsque le bouton "A + B = ?" est press, l'adresse de Somme est donc retrouve avec LierFonction, puis si la fonction a bien t trouve, elle est appele dans un ShowMessage, et enfin, chose ne pas oublier, la DLL est libre de la mmoire, ce qui justifie la sauvegarde dans une variable de son Handle. Comme en tmoigne la copie d'cran, le rsultat est identique la mthode statique du ct utilisateur, mais du ct de la programmation la mthode dynamique nous offre les moyens de contrler les erreurs de chargement de la DLL et de la fonction elle-mme, un niveau o il est encore possible de prvoir une raction "pense" du programme.

Cette premire DLL et l'application l'utilisant sont maintenant termines. Vous avez dsormais en main les lments pour crer vos propres bibliothques de fonctions et les exploiter bon escient. Dans la prochaine partie nous verrons comment aller plus loin avec les DLL et leur trouverons une application qui s'approche plus de quelque chose d'utile qu'une simple somme !

III. Aller plus loin

Le but de cette leur utilisation ncessitant Ils permettront DLL.

partie est d'implmenter une mise en oeuvre plus concrte d'une ou plusieurs DLL et de dans une application que nous dvelopperons. Nous verrons deux exemples, chacun l'une ou l'autre des mthodes statique ou dynamique. de voir plus prcisment comment choisir entre ces deux approches de liaison avec une

III-1. Quand la liaison statique est suffisante


Imaginons un programme simple, un diteur de texte. Nous souhaitons que cet diteur propose deux mthodes d'enregistrement distinctes, dont les implmentations seront stockes dans une DLL. De mme, cette DLL contiendra l'implmentation des deux mthodes de chargement correspondantes. Les lments que nous avons sont les suivants : un nombre de fonctions fini et connu, dont les paramtres et les types de renvoi sont galement connus, le tout implment dans une DLL toute aussi connue. Le choix de la liaison statique est alors ici vident. Tout est dj prpar, il n'y a qu' charger les fonctions ds le lancement de l'application pour que le tout fonctionne. Bien videmment, la mthode dynamique pourrait tre utilise, mais comme vous vous en rendez srement compte, ce serait "beaucoup" de code pour bien peu, dans notre cas. C'est ainsi que la diffrence doit tre faite. Dans tous les cas vous pourrez utiliser la mthode dynamique, mais parfois il sera superflu de faire plus qu'une dclaration statique, moins que vous ayez un besoin impratif de grer ou d'outrepasser des erreurs ventuelles. Dans notre cas, si la DLL n'est pas prsente le programme n'a plus aucun intrt, ce n'est donc pas un mal en soit qu'il ne puisse pas s'excuter ! Passons maintenant l'implmentation de la DLL, puis du programme en lui-mme.

III-1-a. La DLL Notre DLL doit contenir deux fonctions exportes : une de sauvegarde, et une de chargement. Pour l'exemple nous implmenterons une fonction de cryptage par XOR et une autre par dcalage de caractres, l'instar du code de Csar. Rien de bien compliqu, juste de quoi faire deux mthodes diffrentes ! Nous passerons en paramtres aux fonctions de chargement/enregistrement la mthode de cryptage utiliser et la valeur entire qui lui servira. Tout d'abord crons nos deux mthodes de cryptage. Elles se rsument chacune en une ligne, qui crypte le caractre pass en paramtre soit en lui appliquant un XOR avec une valeur donne, soit en incrmentant la valeur ASCII de ce caractre d'un pas galement renseign. Voici la fonction de cryptage XOR :

ere: Char; Valeur: Integer): Char;

actere) xor Valeur) Et voici celle de cryptage par "dcalage" :

ere: Char; Decalage: Integer): Char;

actere) + Decalage);

Ces deux fonctions implmentes, nous allons les exploiter au niveau du chargement et de la sauvegarde. Commenons par cette dernire : il faut lui passer un nom de fichier enregistrer, le texte qu'il doit contenir et les informations concernant le cryptage utiliser. Pour l'enregistrement proprement dit, nous utiliserons un Stream de fichier dans lequel nous crirons le texte fourni en le cryptant, caractre par caractre. Voici le code comment de la fonction d'enregistrement :

, Contenu: pAnsiChar; Methode: TCryptMethod; Valeur: Integer): Boolean; stdcall;

r du contenu enregistrer

de fichier .Create(Fichier, fmCreate);

pas atteint la fin du texte enregistrer

aractre en fonction de la mthode choisie := xorChar(p^, Valeur); := cesChar(p^, Valeur);

dans le fichier et on avance d'un caractre ta, 1);

actre de fin de chane

, 1); erreur on renvoie False

Afin de pouvoir renvoyer False en cas de problme lors de l'criture du fichier, le code a t inclus dans un bloc try..except. Comme vous le voyez, on utilise un pointeur sur caractre pour avancer dans le texte enregistrer, du fait de l'utilisation du type pChar. Cette mthode d'criture caractre par caractre n'est sans doute pas des plus optimises, mais elle a l'avantage d'tre simple, et de suffire pour cet exemple ! Le type TCryptMethod est dfini ainsi, au dbut de l'unit : = 0, cmCesar = 1); Pour la mthode de chargement, un problme apparat : nous ne savons pas l'avance la taille du buffer allouer pour contenir le texte que nous souhaitons charger. Il n'est pas question de laisser la DLL allouer un buffer de la bonne taille, car c'est l'application que doit appartenir la gestion de sa propre mmoire. Nous allons donc employer une "astuce" trs en vogue au niveau des API Windows. Tout comme la fonction d'enregistrement, nous allons demander un nom de fichier, un buffer pour contenir le texte et les informations sur la mthode de cryptage employer. L'astuce, vraiment simple mais efficace, se trouve au niveau de ce buffer : soit l'appelant a effectivement

fourni un pointeur vers un buffer allou en mmoire, auquel cas on y effectue le chargement du texte, soit l'appelant a pass nil en paramtre, et la fonction renvoie alors la taille ncessaire du buffer allouer, en se basant sur la taille du fichier qu'on lui demande de charger. Ainsi le programme appellera un premire fois la fonction avec un buffer nil pour obtenir la taille du fichier, allouera son buffer et rappellera la fonction en lui passant ce dernier pour terminer le chargement. Pour ce qui est du chargement proprement parler, nous crirons le fichier crypt en son ensemble dans le buffer, puis le dcrypterons caractre par caractre avant de rendre la main au programme appelant. Ce qui nous donne le code suivant :

r, Destination: pAnsiChar; Methode: TCryptMethod; Valeur: Integer): Integer; stdcall;

r charger .Create(Fichier, fmOpenRead);

then

nil c'est la taille du buffer que l'on renvoie ze;

fichier tel quel dans le buffer de destination omBeginning); tion^, Stream.Size);

'est pas la fin du texte, on remplace chaque caractre rypte

xorChar(p^, Valeur); cesChar(p^, -Valeur);

Nos deux fonctions sont maintenant prtes (vous remarquerez pour chacune d'elles que la convention d'appel stdcall a t prcise), il reste les dclarer comme exportes pour y avoir accs partir de notre programme. Pour cela, l'ajout de ces trois lignes de code en fin d'unit suffit :

'Sauver' , 'Charger';

Compilez votre DLL, et copiez-la dans un nouveau rpertoire qui contiendra les sources de notre programme. Pour la suite de notre exemple, la DLL aura pour nom "OpFichiers.dll".

III-1-b. Le programme Nous passons donc l'implmentation du programme qui exploitera cette DLL. Commenons par l'interface. Elle doit ressembler la capture d'cran suivante, o les noms des composants utiliss dans le code figurent en rouge :

Au niveau du code, nous allons commencer par les dclarations. Tout d'abord, le type TCryptMethod, puis les deux fonctions Sauver et Charger, le tout dans la section interface de l'unit. Nous y dclarons galement une constante CRYPT_VAL que nous passerons en paramtre aux fonctions pour le XOR et le dcalage de caractre.

= 0, cmCesar = 1);

ues des fonctions de chargement/enregistrement du texte ier, Contenu : pAnsiChar; Methode: TCryptMethod; ur: Integer): Boolean; stdcall; external 'OpFichiers.dll'; ier, Destination: pAnsiChar; Methode: TCryptMethod; ur: Integer): Integer; stdcall; external 'OpFichiers.dll';

Comme prvu nous dclarons donc statiquement les deux fonctions, en prcisant comme nous l'avons vu en deuxime partie le nom de la DLL qui contient le code de chacune, et la convention d'appel utiliser. Nos fonctions peuvent maintenant tre utilises comme n'importe quelle autre fonction au sein de notre code, et nous pouvons donc passer l'implmentation du programme. Son fonctionnement est on ne peut plus simple. Le choix de la mthode de cryptage/dcryptage se fait grce au composant cbxMethode, dont la slection est prise en compte dans les OnClick des boutons de chargement et d'enregistrement. Voyons tout d'abord pour ce dernier :

2Click(Sender: TObject);

tion du fichier crer ame(Fichier, 'Fichier texte (*.txt)|*.txt', '', '', '', True) then

fonction en prvenant d'une ventuelle erreur de sauvegarde ar(Fichier), memTexte.Lines.GetText, TCryptMethod(cbxMethode.ItemIndex), CRYPT_VAL) then de sauvegarde !');

Vous remarquerez que l'on peut difficilement faire plus simple ! Aprs avoir demand un nom de fichier pour le texte enregistrer, on appelle Sauver avec les paramtres ncessaires pour la sauvegarde et le cryptage du texte contenu dans notre mmo. Il faut bien sr que l'ordre des items de cbxMethode concorde avec la dfinition du type TCryptMethod pour que tout se passe correctement. Le code de chargement n'est gure plus compliqu, si ce n'est que l'astuce nonce plus haut implique quelques lignes de code supplmentaires :

1Click(Sender: TObject);

charger ame(Fichier, 'Fichier texte (*.txt)|*.txt') then

le du buffer crer par un premier appel avec Destination = nil siChar(Fichier), nil, TCryptMethod(cbxMethode.ItemIndex), CRYPT_VAL);

r qui recevra le texte charger e);

le passe la fonction Charger pour y rcuprer le texte de notre fichier hier), Contenu, TCryptMethod(cbxMethode.ItemIndex), CRYPT_VAL); emo t(Contenu);

Les commentaires disent tout : dans un premier temps on demande la DLL de nous fournir la taille du buffer allouer puis, une fois la mmoire rserve, on rappelle la fonction Charger pour rcuprer le contenu du fichier et l'afficher dans notre mmo. Comme vous pouvez le voir c'est une mthode assez efficace, et le "cot" d'une ligne de code supplmentaire nous apporte la scurit de grer en interne l'allocation et la libration de la mmoire utilise pour le chargement. Ce programme est maintenant termin. Pour rsumer la situation, la liaison statique nous tait donc permise ici par notre connaissance du nombre et de la dfinition exacts des fonctions qui seraient employes. Celles-ci, implmentes dans la DLL, ont pu tre exploites directement sans autre ajout qu'une dclaration adquate pour chacune d'elle dans l'unit du programme. Cette mthode permet d'ajouter notre guise de nouvelles fonctions d'enregistrement et de chargement l'application, mais n'offre pas cependant toute la flexibilit que l'on peut attendre des DLL. Comme nous allons le voir prsent, une plus grande souplesse peut tre obtenue grce la liaison dynamique.

III-2. Lorsque la liaison dynamique s'impose


Nous allons maintenant nous attaquer au dveloppement d'un programme qui trs sincrement ne servira rien de concret, mais qui va nous permettre de nous intresser un cas d'cole pour ce qui est

des

DLL

les

plugins.

Il existe de nombreuses manires de raliser un systme de gestion de plugins ; ce que nous verrons ici n'est donc pas la mthode, mais une mthode parmi tant d'autres. Voyez les rfrences pour d'autres points de vue sur le sujet. De notre ct, nous irons assez simplement. Imaginons un programme possdant un composant TMainMenu. Nous souhaitons pouvoir ajouter, grce des plugins, un nombre indfini d'items ce menu. Le programme devra donc chercher, dans un rpertoire rserv par exemple, tous les plugins qu'il est cens intgrer son menu. Devant notre mconnaissance du nombre de fichiers qui seront trouvs, et mme de la prsence ou non de plugins, nous n'avons pas le choix d'opter pour une liaison dynamique. Celle-ci permettra de s'adapter chaque situation, et d'viter toute erreur de chargement qui pourrait bloquer le fonctionnement du reste du programme.

III-2-a. La (les) DLL Vous l'aurez compris, les plugins seront des DLL. Et il va de soi qu'il faut instaurer un minimum de "norme" dans ces DLL pour que le programme puisse les reconnatre et les exploiter. Nous allons donc commencer par implmenter une fonction d'identification du plugin. Si le programme ne trouve pas cette fonction dans une DLL, il la considrera comme n'tant pas un plugin valide. Crez une nouvelle DLL et ajoutez-y la fonction suivante :

String; stdcall;

DLL n1'; Cette fonction a un double usage. Par sa prsence, elle indiquera donc au programme qu'il a bien faire un plugin qui lui est destin, et par sa valeur de retour elle donnera l'application le Caption de l'item crer dans le menu. Cet item doit ensuite recevoir des sous-items, qui donneront accs aux fonctionnalits que propose le plugin. La liste de ces sous-items doit tre donne par la DLL, de mme que les fonctions qu'ils vont appeler lors d'unOnClick doivent tre indiques par la DLL et stockes dans celle-ci. Nous donnerons en fait au programme le nom d'exportation de chacune des fonctions, ce qui lui permettra de faire les chargements ncessaires lors du dclenchement de l'vnement OnClick. Nous allons donc crer une fonction qui se chargera de fournir ces informations au programme. Par souci de commodit la fonction renverra un tableau de records listant les couples Item/Fonction, ce qui est la meilleure manire de tout renvoyer d'un seul coup. Nous allons donc dfinir deux types : le type TItem, un record de deux lments et le type TItemsList, un tableau dynamique de TItem. Afin de pouvoir aisment rutiliser ces types dans notre programme, nous allons les dclarer dans une unit part. Crez une nouvelle unit nomme par exemple "PlugUtils.pas" et dfinissez-y nos deux types, dans la partie interface :

ng; ng; TItem; Il nous faut quelque part stocker la liste des items du menu crer. Revenez l'unit de la DLL, et dclarez un tableau constant qui contiendra les Caption des items de notre plugin. Pour l'exemple, nous en crerons trois :

0..2]Of ShortString = ('Item1', 'Item2', 'Item3'); Cette liste tablie, il reste pouvoir la communiquer au programme hte de notre plugin. Nous allons donc crer une fonction GetItemsList qui renverra une tableau de type TItemsList contenant chacun des lments de notre tableau ItemsCaptions associ au nom de la fonction qui lui correspond. Afin de ne pas procder au cas par cas, nous nommerons toutes les fonctions de la mme manire, en prfixant le nom de l'item de la chane "Exec". Voici le code de la fonction GetItemsList :

ous-items crer

TItemsList; stdcall;

du tableau gth(ItemsCaptions));

tions) to High(ItemsCaptions) do

:= ItemsCaptions[i]; procdure associe l'item := 'Exec' + ItemsCaptions[i];

Le fonctionnement de cette fonction est tel qu'il a t dcrit : pour chaque item de ItemsCaptions, on renseigne un nouvel lment du tableau de retour en lui donnant le Caption de l'item et la fonction qui lui est associe dans la DLL. La dernire tape est maintenant de crer ces fonctions, afin qu'un click sur l'un des items puisse tre effectif. Nous ne serons pas trop originaux ici : chaque fonction ne fera qu'afficher un message texte avec un bouton "OK". Pour ne pas alourdir notre DLL, nous utiliserons la fonction MessageBox de l'unit "Windows.pas" plutt queShowMessage. Nous avons donc trois fonctions crer, dont voici les implmentations :

der: TObject); stdcall; 'Vous avez cliqu sur le premier item !!', 'ExecItem1', MB_OK);

der: TObject); stdcall; 'Vous avez cliqu sur le second item !!', 'ExecItem2', MB_OK);

der: TObject); stdcall; 'Vous avez cliqu sur le troisime item !!', 'ExecItem3', MB_OK); Le paramtre de ces procdures n'est prsent que pour des raisons de compatibilit avec le type TNotifyEvent, qui est le type d'vnement de base, et plus particulirement le type de l'vnement OnClick auquel nous associerons nos procdures. Pour finir, il reste une chose essentielle pour que la boucle soit boucle : l'exportation de toutes ces fonctions. Vous avez dj vu comment cela se passait, le code suivant n'a donc pas besoin d'explication supplmentaire :

in

name name name name name

'GetName', 'GetItemsList', 'ExecItem1', 'ExecItem2', 'ExecItem3'; A noter que l'exportation avec des noms corrects est ici trs importante, puisque c'est grce eux que le programme identifiera et utilisera correctement le plugin. Justement, voyons maintenant comment cela se passe du ct de l'application. Compilez la DLL et copiez la dans un sous-dossier "plugins" du rpertoire qui recevra les sources de notre nouveau programme.

III-2-b. Le programme Commenons par un aperu de l'interface :

Le menu "Fichier" ne contient qu'un item "Quitter". La ListBox est l pour afficher des informations sur l'avancement du chargement des plugins. Ce chargement sera fait ds le lancement de l'application, ainsi c'est dans l'vnement OnCreate de notre fiche que nous allons procder l'inspection du dossier "plugins" et l'ajout des diffrents items notre menu. Lors du chargement, le handle de chacune des DLL lies sera ajout dans un tableau dynamique afin d'tre accessible par la suite. Ce tableau est dclar de manire globale dans l'unit :

ndle; Chaque item conservera les informations qui lui sont propres. Afin de ne pas surcharger le code de tableaux en tous genres, nous stockerons le nom de la fonction lui servant d'vnement OnClick dans sa proprit Hint, et l'index du handle de la DLL o trouver cette fonction dans sa proprit Tag. A chacun des items, leur cration, nous assignerons un mme vnement OnClick qui se chargera d'utiliser ces deux informations pour lier et appeler la fonction adquate. L'vnement OnCreate ne contient que trs peu de code en lui-mme. En effet cause du fonctionnement de FindFirst et FindNext, le code de liaison des DLL et d'ajout des items est dcentralis dans une procdureAjoutMenu pour viter que de longues portions de code ne soient rptes inutilement. Cette procdure est imbrique dans la procdure OnCreate, afin de pouvoir rutiliser les variables de celle-ci. Voici dans un premier temps l'vnement OnCreate sans la procdure AjoutMenu :

eate(Sender: TObject);

re ici *}

ers DLL prsents dans le rpertoire "/plugins" ilePath(ParamStr(0)) + '\plugins\*.dll', faAnyFile, SR) = 0 then

re DLL

tres DLL ventuellement prsentes = 0 do

L = un lment de plus ugins) + 1);

ssources alloues pour la recherche

Le fonctionnement avec une boucle while sur FindNext conditionne par le rsultat de FindFirst ne doit pas tre nouveau pour vous ; c'est la mthode fournie dans l'aide de Delphi sur ces deux fonctions de recherche. Ainsi si un premier fichier est trouv, nous commenons par l'ajouter au menu. Le paramtre de AjoutMenu, comme nous le verrons, spcifie l'index o stocker le handle de cette nouvelle DLL dans le tableau Plugins. La valeur 0 correspond donc bien la premire DLL trouve. Ensuite chaque fois qu'une nouvelle DLL est trouve, nous l'ajoutons au menu en spcifiant comme index la taille actuelle de Plugins incrmente de 1. La procdure AjoutMenu se charge avec cette information et les autres variables de OnCreate de lier la DLL au programme et d'en utiliser les fonctions pour ajouter les items et sous-items au menu. En voici le code, qu'il faut insrer aprs la dclaration des variables de OnCreate :

ndex: Integer);

nuItem; st; rcuprer dans la DLL : ion: ShortString; stdcall; ion: TItemsList; stdcall;

tableau de DLL Index + 1); le handle de notre DLL charge ; it en liant la fonction GetName onction(ExtractFilePath(ParamStr(0)) + '\plugins\' + SR.Name, Plugins[Index], 'GetName');

est pas assigne, ce n'est pas un plugin ginName) then

a DLL si besoin <> 0 then gins[Index]); leau de DLL la bonne taille , Index); s la ListBox 'La DLL "' + SR.Name + '" n''est pas un plugin valide.')

veau menu, avec le nom du plugin .Create(Menu); luginName; em);

Box du nouveau plugin trouv 'Nouveau plugin "' + PluginName + '" dans la DLL "' + SR.Name +'"');

onction GetItemsList ierFonction('', Plugins[Index], 'GetItemsList');

problme de chargement il ne faut pas continuer etItemsList) then

d('Fonction "GetItemsList" manquante dans la DLL "' + SR.Name + '"');

ntenant les Items qui formeront le menu st, 0); temsList;

e un un au menu cr pour la DLL sList) to High(ItemsList) do

nuItem.Create(Menu); n := ItemsList[i].Nom; s Hint le nom de la fonction appeler pour l'excution de l'item := ItemsList[i].Fonction; 'index de la DLL contenant la fonction de notre item := Index; qui gre l'vnement OnClick k := ExecItem; -item au menu em); e cet ajout d('---> Ajout de l''item "' + SousItem.Caption + '"');

Tout d'abord afin de pouvoir utiliser le type TItemsList, ajoutez dans la clause uses l'unit "PlugUtils.pas" que nous avons cre lors de l'implmentation de la DLL. AjoutMenu est peut-tre la fonction la plus complexe de cet article, mais elle surtout est plus "massive" que complique. Tout d'abord Plugins voit sa taille incrmente d'un lment, pour recevoir le handle de la DLL, et l'lment nouvellement cr est initialis 0 pour les besoins de la fonction LierFonction. Pour rappel nous avons vu cette fonction dans le troisime paragraphe de la seconde partie de cet article. Vous pouvez ventuellement le consulter pour bien comprendre le droulement du reste du code. Il faut bien sr l'ajouter au code de notre programme. Nous appelons donc LierFonction pour en rcuprer le rsultat dans la variable PluginName. Dans le meilleur des cas, elle pointera alors sur la fonction GetName exporte par la DLL que nous souhaitons ajouter. Sinon, elle contiendra nil, ce qui nous indiquera que la DLL que nous tentons d'ajouter n'est pas un plugin valide. C'est ce distinguo que nous faisons juste ensuite pour viter toute violation d'accs. Si PluginName contient nil, la liaison avec la DLL est libre et la taille de Plugins est dcrmente afin de supprimer l'item qui tait rserv pour cette dernire. Dans le cas contraire, on continue en crant un nouvel item dans le menu dont le Caption est le rsultat de l'appel PluginName. Ensuite on procde avec GetItemsList comme pour la liaison avec GetName, et chaque sous-item est ajout au menu grce la liste rcupre dans ItemsList. C'est cet instant que l'on stocke les informations concernant l'action de chacun de ces items, et que l'on associe leur vnement OnClick la procdure ExecItem. Elle constitue l'vnement OnClick "central", qui se chargera d'appeler en fonction du Sender la fonction qu'il faut dans la bonne DLL. Elle utilisera pour cela notre fonction LierFonction en lui passant en paramtres les informations auparavant stockes dans les proprits Hint et Tag de l'item.

em(Sender: TObject);

Sender: TObject); stdcall;

pas un TMenuItem on sort nuItem) then Exit;

tion associe l'item dans la DLL m(Sender); tion('', Plugins[Item.Tag], Item.Hint); fonction

Pour l'appel de Lierfonction, notez que puisque Plugins[Item.Tag] est un handle valide de DLL, il n'y a pas besoin de fournir le chemin d'un fichier DLL charger. N'oubliez pas de dclarer ExecItem dans la partie Public de TForm1 pour qu'elle puisse tre utilis comme vnement des Items Le code de chargement des plugins est maintenant termin. Il ne reste qu' librer les DLL la fermeture du programme pour parfaire le tout. Il suffit pour cela de grer l'vnement OnClose de la fiche, en implmentant le code suivant :

ose(Sender: TObject; var Action: TCloseAction);

to High(Plugins) do [i]); Le programme est maintenant bel et bien termin. Vous pouvez le tester en dupliquant autant de fois que vous le dsirez la DLL que nous avons compile prcdemment, les menus s'ajouteront automatiquement et pour chaque item vous aurez le message correspondant. Cette mthode de liaison dynamique est donc trs puissante, car elle offre une grande flexibilit tout programme qui l'utilise et permet ainsi de grer au mieux toute sorte de modules, de plugins etc. Comme vous l'avez peut-tre remarqu il y a toutefois certaines choses auxquelles il faut faire attention pour viter diverses problmes. C'est ce que nous allons traiter dans la dernire partie de cet article.

IV. Rflexes prendre, astuces, ...

IV-1. Partager des types entre application et DLL


Comme dans le dernier programme que nous venons de dvelopper, il est parfois ncessaire de crer des types spcifiques pour changer des donnes entre une DLL et l'application qui l'exploite. Dans notre exemple il n'y en avait que deux, TItem et TItemsList, mais dans de vrais projets cela peut prendre une autre dimension. Il est alors fortement conseill, et c'est ce que nous avons fait ici, de dclarer tous ces types (et mme ventuellement des fonctions communes) dans une unit part, pour ne pas rpter les dclarations entre les units du programme et de la DLL. Cette prcaution permet par ailleurs de modifier beaucoup plus facilement ces types, et ainsi d'viter les

problmes qui pourraient arriver dans le cas d'un oubli de rpercussion d'une modification entre deux fichiers, par exemple.

IV-2. Veiller aux types de variables utiliss


Ce n'est pas une nouvelle, les DLL sont faites pour tre utilises par plusieurs programmes de manire totalement transparente. Seulement, plusieurs programmes peut signifier diffrents langages de programmation, et les choses se compliquent alors. En effet, les types de donnes de base peuvent avoir entre les langages des caractristiques bien diffrentes, comme notamment la place prise en mmoire par une variable d'un type donn. Si vos DLL sont destines tre exploites par des programmes qui ne seront pas ncessairement dvelopps avec Delphi, il vaut donc mieux utiliser des types gnriques, non spcifiques Delphi. Il faudra donc pour cela prfrer les types dfinis par Windows, ou au minimum vrifier que le type de variable que vous vous apprtez utiliser correspond bien au type attendu par le programme qui exploitera votre DLL. Ainsi, faites attention lorsque vous utilisez des types propres Delphi. Par exemple, le type integer est dfini comme un nombre entier sign de quatre octets. Cependant, dans des versions futures et grce l'volution des architectures des processeurs, ce type pourrait trs bien devenir un entier sign de huit octets. Dans ce cas, on pourrait alors avoir de nombreuses violations d'accs ou au mieux des valeurs incohrentes. Les types fondamentaux dont les tailles ne sont pas censes changer sont les suivants :

Shortint : 8 bits sign Smallint : 16 bits sign Longint : 32 bits sign Int64 : 64 bits sign Byte : 8 bits non sign Word : 16 bits non sign Longword : 32 bits non sign

Dans le mme registre, attardons nous sur le type string. Vous vous souvenez sans doute de l'avertissement de Borland. Pour donner plus de prcisions, "borlndmm.dll" est une DLL qui sert remplacer le gestionnaire de mmoire de Windows par dfaut. Cela parce que le type string n'est pas du tout un type standard, et que pour le grer Borland a donc eu besoin de fournir un moyen personnalis. Cependant leur solution est plutt contraignante, car elle limite le fonctionnement de ces dernires des applications Delphi qui utilisent l'unit "ShareMem.pas". Il est donc prfrable, pour s'affranchir de cette contrainte, de n'utiliser dans les paramtres des fonctions de vos DLL que des types pChar ou ShortString, comme nous l'avons fait dans tous les codes de cet article. Notez bien qu'il ne vous est pas du tout interdit d'utiliser le type string au sein de votre DLL. L'important est de ne pas l'utiliser dans les changes entre votre DLL et le programme qui l'emploie.

Si vous souhaitez une alternative ShareMem et l'utilisation de Borlndmm.dll, il existe Cette unit a pour but de remplacer Sharemem.pas en bien des points : allocations de mmoire plus rapides, un

Merci Romain Toutain pour cette information !

IV-3. Les conventions d'appel


Les conventions d'appel rglent le passage des paramtres des fonctions et procdures. Il existe cinq conventions diffrentes :

Pascal Register Stdcall Cdecl Safecall

Les diffrences qu'elles apportent sur le passage des paramtres une fonction ou une procdure se jouent trois niveaux :

L'ordre dans lequel sont empils les paramtres en mmoire A qui revient la responsabilit (entre l'appelant et l'appele) de librer la mmoire occupe par Le passage ou non des paramtres par les registres processeur
La convention register est la seule passer les paramtres par les registres processeur. Dans le cas o il y a plus de trois paramtres, le quatrime et les suivants seront empils en mmoire dans l'ordre de leur dclaration. Cette convention, qui est celle utilise par dfaut lorsque les optimisations sont actives, remplace la convention pascal. Celle-ci n'existe encore que par souci de compatibilit. Elle est la convention par dfaut au cas o les optimisations ne sont pas actives. Dans les deux cas, c'est la routine appele que revient la tche de librer la mmoire alloue aux paramtres. La convention stdcall (Standard Call) est la convention principalement utilise par Windows, dans toutes ses DLL et donc notamment dans les DLL contenant les fonctions de l'API. Cela en fait la convention la plus "standard" des cinq, et c'est pourquoi nous l'utilisons pour communiquer entre nos DLL et nos programmes. Lors d'un appel une routine dclare avec stdcall, les paramtres sont empils en mmoire dans l'ordre inverse de leur dclaration, et c'est la routine qui doit librer la mmoire alloue pour ces derniers. La convention cdecl est la convention des programmes et librairies crits en C et C++. Elle est prcise par Borland comme tant moins efficace que stdcall. Avec cette convention, les paramtres sont galement empils en mmoire dans l'ordre inverse de leur dclaration, mais c'est au programme appelant qu'il revient la responsabilit de librer la mmoire qui leur est rserve. Enfin, la convention safecall est identique par ses caractristiques stdcall. Elle est utilise dans le cadre des objets Automation et sert mettre en place les notifications d'erreurs COM interprocessus, selon l'aide en ligne de Delphi. Pour conclure sur les conventions d'appel, la principale chose que vous devez garder l'esprit lorsque vous dveloppez et/ou exploitez des DLL, c'est qu'il est impratif que les fonctions soient dclares et appeles avec des conventions d'appel strictement identiques. Sans cela, vous risquez bon nombre d'erreurs, plantages ou rsultats hasardeux. Si vous souhaitez une illustration de ce qu'on peut appeler "rsultat hasardeux", essayez avec le programme Somme de la premire partie de dclarer la fonction importe en register par exemple, en gardant la DLL d'origine, puis faites effectuer au programme la somme "0 + 0" ! les paramtres

IV-4. Dboguer une DLL


Comme pour tout programme, il arrive que le code d'une DLL pose quelques problmes et il est alors ncessaire de la dboguer. Cela dit, ce n'est pas aussi automatique qu'avec une application car une DLL n'est pas excutable et a donc besoin d'un "hte" pour pouvoir tre charge en mmoire et dbogue. Pour avoir un tel hte, il vous faut donc tout d'abord une application compile qui utilise le code de la DLL que vous souhaitez dboguer. Cette application prte, ouvrez le projet de votre DLL dans Delphi et accdez la fentre "Paramtres" dans le menu "Excuter" :

Paramtres d'excution Ici, renseignez le chemin de votre application dans le champ "Application hte" et d'ventuels paramtres pour celle-ci. Si vous voulez utilisez un rpertoire de travail diffrent de celui de votre application, vous pouvez galement l'indiquer. Une fois cette fentre valide, vous pourrez lancer la commande "Excuter" et utiliser les fonctionnalits de dbogage dans votre DLL. L'onglet "Distant" permet d'utiliser le dbogage distance grce au serveur de dbogage distance de Borland. Cette option ne sera pas aborde ici.

Conclusion
C'est maintenant la fin de cet article. J'espre qu'il vous a permis de bien cerner comment se crent et s'emploient les DLL avec Delphi, et que les exemples de la troisime partie vous ont convaincu de leur efficacit dynamiser vos applications. Je suis ouvert toute remarque, suggestion ou critique constructive quant cet article. Il vous suffit de m'envoyer un message priv par le biais du forum. Vous pouvez tlcharger les sources des exemples de la troisime partie ces adresses : Exemple de la mthode statique Exemple de la mthode dynamique Si ces liens ne fonctionnent Exemple de Exemple de la mthode dynamique pas la chez vous, utilisez mthode ces miroirs : statique

Remerciements
Merci beaucoup Delphiprog, Laurent Dardenne, LLB, Mac LAK et Nono40 pour leurs remarques et leur aide. Merci galement N*M*B qui m'a signal une erreur dans les fichiers tlcharger et une optimisation de mon code.

Rfrences

ressources, par Nono40

DLL ne contenant que des icnes - Crez une DLL de

Conventions d'appel - Dtails sur les conventions d'appel dans l'article Utilisation de l'assembleur en ligne avec Delphi, par Nono40

Raliser un plug-in comportant un composant Deux mthodes avances pour raliser des plugins, par Clorish et sjrd

Le livre Delphi 7 Studio d'Olivier Dahan et Paul Toth Tout un chapitre sur les DLL, un systme de plugins et des astuces !

Utilisez les ressources dans votre application Delphi - Un tutoriel de Delphicool pour apprendre manipuler les ressources

FAQ Delphi - Articles de la FAQ sur les DLL

Tutoriels - Autres ressources mises disposition sur developpez.com

Dynamic-Link Libraries - Pages de la MSDN sur les DLL

FastSharemem: A Fast, Lightweight Sharemem Replacement - La page de l'unit FastSharemem

Iczelion's Win32 Assembly Homepage - Les pages d'Iczelion, o on trouve entre autre une trs bonne documentation du format PE

formats de fichiers.

Wotsit - Une mine d'or pour trouver des descriptions de

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2005 Olivier Lance. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose.

Responsable bnvole de la rubrique Delphi : Franck Soriano - Contacter par email

Developpez.com
Nous contacter Participez Informations lgales

Services
Forum Delphi Blogs Hbergement

Partenaires
Hbergement Web Copyright 2000-2012 - www.developpez.com