Historique des mises à jour : n° 1
Heure de mise à jour : 2001-11-01 20:09
Mis à jour par : Musicwind®
Note de mise à jour : première ébauche terminée.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~
résumé:
Cet article explique comment exporter des classes dans une Dll - de nombreuses sous-classes basées sur une classe abstraite spécifique. Cette technologie utilise l'idée du polymorphisme, permettant d'obtenir des effets similaires aux plug-ins.
Lecteurs visés :
Comprendre le concept de polymorphisme ; comprendre le concept de métaclasse.
Difficulté technique :
6/10 .
Pour exporter une classe depuis une Dll, la première chose à laquelle vous devez penser est d'utiliser le package bpl. Un inconvénient de cette méthode est que l'utilisateur doit savoir quelles classes sont contenues dans le package, ce qui signifie que le nom de la classe doit être connu - c'est une limitation dans un certain sens. Imaginez une situation dans laquelle l'utilisateur définit une couche inférieure. classe abstraite, puis de nombreuses classes d'application (béton classe), puis, pour l'utilisateur, il espère pouvoir utiliser ces classes sans connaître les classes spécifiques - cela semble un peu mystérieux de dire cela, mais la situation réelle est vraie, car elle ne peut pas être prédite lors de la définition des classes abstraites. Comment y aura-t-il de nombreux cours spécifiques à l’avenir ? Alors, quel type de technologie sera nécessaire pour répondre à une telle demande ?
En fait, la difficulté technique de sa mise en œuvre n'est pas très difficile - l'auteur consacre ici son expérience pratique à chacun, afin d'attirer de nouvelles idées, et espère voir d'autres méthodes meilleures !
Ce qui suit présente d'abord quelques connaissances de base impliquées dans cette méthode, puis utilise un exemple pour illustrer la mise en œuvre spécifique.
1. Notions de base
La méta-classe (méta-classe), également appelée type de référence de classe (type de référence de classe), peut être considérée comme un type de classe, et la valeur d'une variable déclarée avec ce type représente une classe. Par exemple:
taper
TClass = Classe de TObject ;
Ceci déclare un type de métaclasse. Ensuite, vous pouvez avoir des déclarations de variables comme celle-ci :
Var
Classe A : Classe T ;
Ensuite, vous pouvez l'utiliser comme ceci :
AClass := TObject;
ou:
AClass := TButton;
ou:
AClass := TForm;
etc.
Étant donné que TClass est une métaclasse de type TObject et que TButton, TForm, etc. sont tous dérivés de TObject, les valeurs telles que TButton et TForm sont acceptables pour AClass.
Ensuite, nous pouvons utiliser l'idée de polymorphisme et utiliser de manière flexible la variable de classe AClass. Il s'agit également des connaissances de base pour la mise en œuvre spécifique ci-dessous.
2. Mise en œuvre spécifique
La première étape consiste à créer une classe abstraite :
Nous utilisons une déclaration aussi simple. La classe abstraite fournit uniquement une méthode abstraite, mais cela n'affecte pas notre description du problème :
TMyBaseForm = Classe (TForm)
Protégé
fonction GetTitle : pchar virtuel ;
fin;
MyBaseFormClass = Classe de TMyBaseForm ;
Ne discutons pas du nombre de méthodes et d’interfaces pratiques qu’offre une telle classe abstraite, car ce dont nous voulons discuter est une faisabilité technique. Supposons que l'intention initiale de l'auteur en définissant cette interface est d'obtenir un nombre quelconque de titres changeants et que la valeur de retour spécifique de GetTitle doit être implémentée par les sous-classes. De plus, l'auteur espère également que le code de la sous-classe pourra être implémenté dans une Dll et séparé du programme principal - cette méthode a le goût d'un plug-in, et peut également permettre de réaliser certaines fonctionnalités de Plug&Play - n'est-ce pas ? n'est-ce pas assez attrayant ? Alors, que devriez-vous faire ensuite ?
Premièrement, le programme principal et le programme Dll doivent inclure les unités déclarées ci-dessus. Ensuite, le programme principal est responsable de la mise en œuvre d'un pilote - du chargement dynamique de la Dll et du chargement dynamique des classes, et la Dll est responsable de la mise en œuvre des sous-classes.
Parlons d’abord de Dll. Que devrait faire Dll ?
La deuxième étape consiste à exporter la sous-classe en Dll :
Nous avons conçu les deux fonctions exportées suivantes :
1. fonction GetClassCount : entier ; stdcall ;
Dites à l'appelant qu'il existe plusieurs sous-classes dans cette Dll ;
2. function GetClassTypeByIndex(const iIndex: entier;
var ClassType : MyBaseFormClass) : WordBool ;
Obtenez une sous-classe spécifique par index. Notez que le type de ClassType ici est MyBaseFormClass, ce qui indique que sa valeur sera une classe définie héritée de TMyBaseForm.
En voici une implémentation possible :
fonction GetClassCount : entier ;
commencer
result := 3; //Indique que 3 classes sont exportées dans cette Dll
fin;
function GetClassTypeByIndex(const iIndex: entier;
var ClassType : MyBaseFormClass) : WordBool ;
commencer
résultat := Vrai ;
cas iIndex de
0 : Type de classe := TFrmTest1 ;
1 : Type de classe := TFrmTest2 ;
2 : Type de classe := TFrmTest3 ;
autre
résultat := Faux;
fin;
fin;
Bien entendu, les unités où se trouvent TFrmTest1, TFrmTest2 et TFrmTest3 doivent être incluses dans la liste d'utilisation de l'unité. L'implémentation de TFrmTest1 peut ressembler à ceci :
TFrmTest1 = Classe (TMyBaseForm)
protégé
fonction GetTitle : PChar ;
fin;
fonction TFrmTest1.GetTitle : Pchar ;
commencer
result := 'Bonjour de TFrmTest1';
fin;
Enfin, n'oubliez pas d'ajouter GetClassCount et GetClassByIndex à la liste des exportations. Ensuite, lors de la construction du projet Dll, veuillez cocher « utiliser le package d'exécution » dans le package d'options du projet. Les raisons spécifiques seront discutées plus tard.
À ce stade, le travail sur Dll est terminé.
La troisième étape est la mise en œuvre du moteur principal du pilote du programme :
Cette étape est relativement simple : il s'agit simplement de charger dynamiquement la DLL, puis d'appeler la fonction GetClassCount, puis d'appeler GetClassByIndex. Code clé :
Var AClass : TMyBaseClass ;
AForm : TMyBaseForm ;
I, iCount : entier ;
blResult : booléen ;
commencer
//Omettez la partie concernant le chargement de la bibliothèque dynamique, en supposant que FPGetClassProc pointe vers la fonction GetClassCount et que FPGetClassByIndexProc pointe vers GetClassByIndex, alors :
iCount := FPGetClassProc;
pour I := 0 à iCount ?C 1 faire
commencer
AClass := FPGetClassByIndex(I, blResult);
si blResult alors
commencer
AForm := AClass.Create(application);
AForm.Caption := AForm.GetTitle;
AForm.Afficher;
fin;
fin;
//…
fin;
Notez que, comme pour Dll, vous devez également choisir d'utiliser le package d'exécution lors de la création du fichier de sortie. En effet, ne pas utiliser le package d'exécution entraînera plusieurs copies de la même classe en mémoire, donc l'utilisation de l'opérateur Is sur celles-ci renverra False.
Musicwind®@HangZhou.Zhejiang.Chine
2001-11-01
Plus d'articles
[ Fin de l'article]