begin process at 2012 02 17 06:03:16
  Trouver un code source :
 
dans
 
Accueil > 

Tutoriels

 > 

Trucs & Astuces

 > FOURNIR DES FONCTIONS CALLBACKS AUTRES QUE STDCALL

FOURNIR DES FONCTIONS CALLBACKS AUTRES QUE STDCALL


 Information sur le tutoriel

Note :
Aucune 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.

Commentaires

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

Commentaire de ShareVB le 14/07/2005 12:13:13

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

ShareVB

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

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), 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

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 2,371 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales