SUPINFO International University

SUPINFO Institute of Information Technology
Laboratoire Microsoft




Tous les Articles du Laboratoire Microsoft

Microsoft vous invite au concert d'Alanis Morissette !
Accueil > Articles > Actualité
Auteurs 
Yann ALET
LABORATOIRE SUPINFO DES TECHNOLOGIES MICROSOFT
Formateur


 Tous les articles de cet auteur

3,1/5

Assez Bien


59197
69/218

Un peu plus loin dans les Dlls

Une fonction déjà présente

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.


L'utilisation de paramètres

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...

Et les objets ?

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


En Savoir Plus 
Evaluez cet article 


Pour afficher ou poster un commentaire, cliquez sur ce lien : Forum-Microsoft



Retrouvez ci-dessous les autres sections du Laboratoire Microsoft