Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

FOURNIR DES FONCTIONS CALLBACKS AUTRES QUE STDCALL


Information sur le tutorial

Catégorie :Trucs & Astuces Date de création : 14/07/2005 10:58:24 Vu : 4 308 fois

Note :
Aucune note

Commentaire sur cette source (3)
Ajouter un commentaire et/ou une note


Description

Ce tutoriel expose la méthode pour fournir des pointeurs de fonctions cdecl, fastcall, thiscall et pascal.

Tutorial

Fournir les fonctions CALLBACK autres que stdcall

 

 

Le problème est différent des appels de pointeurs defonction. En effet, on n’a pas besoin d’objet mais simplement d’une structurequi contiendra du code ASM et un pointeur lpfn vers ce code. Il faut transformerun appel cdecl, fastcall, thiscall, (voire pascal) en stdcall de fonction demodule BAS.

 

Nous ne traiterons ici que le casde fonction renvoyant des valeurs tenant dans les registre EAX et EDX.Sinon, il faudra tenir compte du fait que le premier paramètre est un pointeurvers une zone mémoire.

 

Transformer en appel stdcall un appel…

 

Dans tous les cas, on passera le pointeur lpfn commepointeur de fonction callback à la fonction demandeuse et on passera auxfonctions de constructions de fonction callback, le pointeur AddressOf de lafonction VB.

 

Le code aura la structuration suivante :

 

Public TypeCallback

    lpfn As Long

   

    Code(0 To <taille nécessaire>) As Long

End Type

 

Public SubInitCallback(ByRef lpCB As Callback, ByVal lpfnCallback As Long, <autresparamètres dépendants de la convention d’appel>)

    WithlpCDeclCB

        'on remplit avec le code fixe et les paramètres dépendantde la fonction

        .Code(0) =&HXXXXXXXX

       ‘……

        .Code(n)= &HXXXXXXXX

       

        .lpfn =VarPtr(.Code(0))

    End With

End Sub

 

            Cdecl

 

Le problème est que la fonction appelée ne doit passupprimer les paramètres de la pile. Hors VB supprime toujours les paramètresde la pile à la fin des fonctions (stdcall). Il faudra donc dupliquer lesparamètres pour laisser la pile dans son état normal.

 

Il faut donc :

  • On alloue de l’espace sur la pile pour un double des paramètres
  • On copie les paramètres et l’adresse de retour dans cet emplacement
  • On saute dans la fonction

 

On aura donc la pile suivante avant l’appel à la fonctioncallback VB :

 

Paramètre-n

Paramètre-2

Paramètre-1

Paramètre-n

Paramètre-2

Paramètre-1

ReturnAddress

 

En prenant en compte le fait qu’il faut utiliser lesregistres EDI et ESI et donc les sauvegarder, cela donne le code ASM suivant :

      mov ecx, 0x12345678 //on copie lataille des donnée dans ECX :

//0x12345678 sera remplacé par la taille des paramètres

      add ecx, 4          //on ajoute 4 pour l'adresse de retour

 

      lea eax,[esp - 4]   //on charge l'adresse de la pile - 4 pour EDI - 4

  //pour ESI

subeax,ecx         //onsoustrait la taille des paramètres à

  //l'adresse nouvelle

 

      test [eax],ecx      //on vérifie que la page est chargée avant de

  //copier au cas où onaurait changé de page

 

      mov [eax],edi       //on sauvegarde les registres EDI et ESI

      mov [eax + 4],esi   //

 

      mov esi,esp         //oncalcule l'adresse de la source pour la copie

  //des paramètres

           

      lea edi,[eax + 8]   //on calcule l'adresse de la zone des paramètres

  //copiés

           

      cld                //copie vers le haut

 

      shr ecx,2         //copie 4 octetspar 4 octets

      rep movsd         //on copie les ecxDWORDs

 

      mov esp,eax         //on place la pile à l'adresse des (données

  //copiées + EDI + ESI)

 

      pop edi             //on restaure les registres EDI et ESI

      pop esi

           

      mov eax,0x12345678  //on copie l'adresse de la fonction stdcall à

//appeler : 0x12345678 sera remplacé par l'adresse

      jmp eax             //on appelle la fonction

 

 

            Fastcall

 

Le problème est l’ordre des paramètres :

  • S’il y a un ou plusieurs paramètres entiers ou pointeurs (<= 4 octets), on les met en premier dans le prototype VB
  • On met donc tout autres paramètres en suivant dans leur ordre de déclaration

 

Le code dépend du nombre de paramètres pouvant être mis dansles registres :

    • S’il n’y en a pas : l’ordre des paramètres ne change pas
    • S’il y en a un, le code met celui ci (ECX) en premier paramètre
    • S’il y en a deux, le code met ECX en premier et EDX en deuxième

 

Le code sera le suivant :

      pop eax //on récupère l'adresse deretour

 

      //ce code sera soit modifié suivant lenombre de « registrables »

      //s'il y a un deuxième paramètrepouvant tenir dans un registre

      PUSH EDX

      //s'il y a un premier paramètrepouvant tenir dans un registre

      PUSH ECX

 

      push eax //on remet l'adresse deretour

 

      mov eax,0x12345678  //on copie l'adresse de la fonction stdcall à

 //appeler : 0x12345678sera remplacé par l'adresse

      jmp eax             //on appelle la fonction

 

 

            Thiscall

 

Le plus dure est de connaître la structure de l’objet C++, àsavoir les variables privées. Il faut pour cela, disposer du fichier .h ettraduire les membres de type variable de l’objet en structure VB. Il ne fautpas confondre le pointeur This des objets COM (et VB) avec le pointeur This desobjets C++. Ce dernier a un pointeur vers une vtable, uniquement s’ilcontient des fonctions virtuelles. Un objet C++ n’est pas une entitéautonome au sens de COM. La seul différence entre une fonction stdcall et uneméthode thiscall est la décoration de son nom par le compilateur et le pointeurthis dans ECX.

 

Le code devra donc simplement mettre le pointeur This de ECXcomme premier paramètre. Le code sera le suivant :

      pop eax //on récupère l'adresse deretour

      push ecx //on met le pointeur ThisC++ sur la pile

      push eax //on remet l'adresse deretour

 

      mov eax,0x12345678  //on copie l'adresse de la fonction stdcall à

 //appeler : 0x12345678sera remplacé par l'adresse

      jmp eax             //on appelle la fonction

 

 

            Pascal

 

Là c’est simple, il suffit que les paramètres soient mis enordre inverse. Si on a a,b,c dans le prototype pascal, on met c,b,a dans lafonction BAS.

signaler à un administrateur
Commentaire de ShareVB le 14/07/2005 11:00:02

Je cite ma source, tout en disant que ce n'est pas du copier coller, ni du texte, ni du code (l'auteur ne traite que cdecl) :

Advanced Visual Basic 6
Power Techniques for Everyday Programs
Matthew Curland
www.powervb.com

Si vous voulez encore plus d'infos sur VB, achetez et lisez ce livre...

ShareVB

signaler à un administrateur
Commentaire de ShareVB le 14/07/2005 12:13:13

un projet exemple est disponible : http://www.vbfrance.com/code.aspx?ID=32703

ShareVB

signaler à un administrateur
Commentaire de ShareVB le 11/08/2006 22:19:29

salut à tous,

retrouvez ce tuto sur mon site perso à www.sharevb.net...rubrique Programmation\VB\

ShareVB

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Décembre 2008
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,031 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.