|
Tous les Articles du Laboratoire Microsoft
Un peu plus loin dans les Dlls
|
|
|
Vous avez dû remarquer que lorsque vous avez créé votre projet, une fonction était déjà présente,
il s'agit de la fonction DllMain. Chaque Dll doit avoir une fonction DllMain : elle peut être appelée
à divers moments, lorsque la Dll est initialisée ou rechargée. Nous n'utiliserons pas ici cette
fonction, mais libre à vous d'y placer du code à exécuter lors du chargement de la Dll.
|
|
|
|
|
|
Une fonction ne serait rien sans l'utilisation de paramètres... Créons une petite fonction qui
additionnera deux entiers. Sous Visual C++, ajoutez le prototype de la fonction dans le fichier header :
int __stdcall Additionne(int a, int b);
|
Puis, dans le fichier source .cpp, le corps de la fonction :
int __stdcall Additionne(int a, int b)
{
return (a + b);
}
|
Enfin, ajoutez ceci au fichier d'exportation (j'écourte un peu, vous savez comment faire...) :
Additionne = ?Additionne@@YGHHH@Z PRIVATE
|
Compilez le tout... Ca devrait fonctionner.
Désormais, on dispose d'une fonction qui attend deux ints (deux Longs sous VB), et qui en renvoie
la somme sous forme d'un int (d'un Long sous VB). Je sais qu'il est facile d'obtenir un overflow,
mais ici n'est pas la question ! Je vous rappelle que mes exemples sont simplifiés au maximum...
A vous de régler le problème par la suite...
Comment utiliser la Dll sous VB ?
Reprenez le projet créé auparavant, et déclarez la nouvelle fonction dans le module :
Public Declare Function DllAdditionne Lib "dll_fichier.dll"
Alias "Additionne" (ByVal a As Long, ByVal b As Long) As Long
|
La fonction prend cette fois deux paramètres, tous les deux des Longs, et renvoie un Long.
Pensez à préciser le mot-clef ByVal, qui va permettre de passer l'argument par valeur à la Dll.
Les pointeurs et les chaînes de caractères :
Les pointeurs :
Si vous spécifiez ByRef, c'est l'adresse du Long qui sera passé en argument. Il faudrait alors le traiter avec
un pointeur sur int du côté de la Dll, comme ceci :
int __stdcall AdditionnePtr(int* a, int* b)
{
return ((*a) + (*b));
}
|
Remarquez qu'avec les pointeurs, il est possible de modifier directement une valeur d'une variable déclarée
sous VB... mais les pointeurs sont difficilement gérables sous VB, car officiellement non manipulables,
mais jetez donc un coup d'oeil aux fonctions non documentées : VarPtr(variable), ObjPtr(objet), StrPtr(string)...
Comment passer une chaîne de caractères en argument ?
Une chaîne VB doit être de taille fixe pour pouvoir être manipulée par la Dll. Voici une déclaration correcte :
Dim Chaine As String * 255
|
Elle doit être passée par Valeur (ByVal) et être attendue comme un pointeur sur char en C++. Attention au
dépassement d'espace mémoire...
|
|
|
|
Pour terminer cette introduction à la programmation de Dlls, abordons un point essentiel, et répondons
à une question que tout le monde se pose (si si...) : Qu'est-ce qu'on mange ce soir ? Pardon : Peut-on
exporter des classes avec une Dll ?
La réponse est simple : des pâtes, ah... pardon : oui et non... En fait, il est possible d'exporter des
classes, mais elles ne seront pas réutilisables sous VB car non importables dans cet environnement !
On doit avoir recours à une petite supercherie pour parvenir à nos fins...
En fait, il va nous falloir écrire une interface pour pouvoir utiliser notre classe ! En clair, chaque
méthode dont nous voudrons disposer dans notre programme VB, y compris les constructeurs/destructeurs,
devra être appelée à partir d'une fonction qui sera, elle, exportée par la Dll.
Passons à un petit exemple, cela vaut mieux qu'un long discours...
Créez une petite classe sous VisualC++, par exemple, celle-ci :
class Test
{
public:
Test(); // Constructeur, initialisa A à 0
~Test(); // Destructeur, ne fait rien de spécial
int SetA(int a); // Affecte a à A
int GetA(void); // Renvoie A
private:
int A; // Donnée privée : A
};
|
... Je passe les définitions des méthodes qui sont enfantines !
Cette classe toute simple ne peut pas être exportée vers VB. On ne pourra jamais instancier un objet
du type Test directement dans cet environnement de programmation.
D'où l'intérêt de fonctions intermédiaires... En fait, nous allons utiliser les adresses mémoire des objets
instanciés dans la Dll. La fonction "wrappée" du constructeur renverra donc l'adresse de l'objet Test
créé par la Dll. De même, la fonction du destructeur prendra en argument l'adresse de l'objet à détruire.
Les adresses renvoyées pas la Dll sont récupérées sous VB sous forme de Long (4 octets), pour pouvoir
être réutilisées dans l'appel de fonctions.
Voilà pour le principe de fonctionnement global... Observez maintenant les fonctions de l'interface :
// On renvoie l'adresse d'un nouvel objet Test
Test* __stdcall Test_Constr(void)
{
return (new Test);
}
// Détruit un objet Test à partir de son adresse
int __stdcall Test_Destr(Test* Objet)
{
delete Objet;
return 0;
}
// Appelle la méthode SetA() d'un objet à partir de son adresse
int __stdcall Test_SetA(Test* Objet, int a)
{
Objet->SetA(a);
return 0;
}
// Appelle la méthode GetA() d'un objet à partir de son adresse
int __stdcall Test_GetA(const Test* Objet)
{
return Objet->GetA();
}
|
Et l'importation de ces méthodes sous VB :
Public Declare Function DllTest_Constr Lib "dll_fichier.dll"
Alias "Test_Constr" () As Long
Public Declare Function DllTest_Destr Lib "dll_fichier.dll"
Alias "Test_Destr" (ByVal Adresse As Long) As Long
Public Declare Function DllTest_GetA Lib "dll_fichier.dll"
Alias "Test_GetA" (ByVal Adresse As Long, ByVal a As Long) As Long
Public Declare Function DllTest_SetA Lib "dll_fichier.dll"
Alias "Test_SetA" (ByVal Adresse As Long) As Long
|
Je vous invite à bien regarder les exemples du code afin de mieux comprendre son utilisation... N'oubliez pas
de désallouer correctement la mémoire après chaque allocation sous VB, et n'oubliez pas également de gérer
les erreurs concernant les adresses mémoires passées à partir de VB. Un petit try-catch ne peut pas faire de mal !!!
|
Sommaire
1 - Introduction
2 - Dlls for dummies
3 - Première approche
4 - Un exemple concret
5 - Un peu plus loin...
6 - Conclusion
|
|
 |
Pour afficher ou poster un commentaire, cliquez sur ce lien : Forum-Microsoft
|
|
|
 |