: les Delegates [C++ pour les hommes, les vrais] - C++ - Programmation
Marsh Posté le 16-11-2004 à 16:06:07
J'ai rien compris...
Marsh Posté le 16-11-2004 à 16:22:13
euh .... y a des trucs templates qui font ca proprement tu sais
EDIT : COPITEUR
http://www.codeproject.com/cpp/SoloGenericCallBack.asp
Marsh Posté le 16-11-2004 à 16:29:16
copiteur ? mon cul, c'est du 100% trouvé par moi, maintenant la technique dite du "thunkt est pas neuve en elle meme
Marsh Posté le 16-11-2004 à 16:38:33
Cette technique s'appelle le thunking et est à la base de l'encapsulation Win32 dans des libs comme OWL ou ATL. Elle ne fonctionne pas sur certains processeurs récents (flag NX) & certains noyaux Linux / XP SP2 car la mémoire allouée n'a pas le droit en exécution...
Marsh Posté le 16-11-2004 à 16:48:49
HelloWorld a écrit : Elle ne fonctionne pas sur certains processeurs récents (flag NX) & certains noyaux Linux / XP SP2 car la mémoire allouée n'a pas le droit en exécution... |
Je lui ai déjà dit, mais il m'a dit qu'il s'en foutait et que depuis qu'il faisait des Delegates Colgate, son sexe avait triplé de volume.
Bref, je crois qu'il serait mieux à faire du Java et du SQL, et laisser la vraie programmation aux spécialistes.
Marsh Posté le 16-11-2004 à 17:02:23
Lam's a écrit : Je lui ai déjà dit, mais il m'a dit qu'il s'en foutait et que depuis qu'il faisait des Delegates Colgate, son sexe avait triplé de volume. |
j't'ai repondu
Marsh Posté le 16-11-2004 à 17:04:38
Y'a pas de solution portable, déjà à cause de l'asm. Mais en spécifique c'est faisable, à condition d'allouer de la mémoire exécutable avec VirtualAlloc + VirtualProtectEx( PAGE_EXECUTE ).
Marsh Posté le 16-11-2004 à 17:10:54
heink ? boost::function et boost::bind c'est bien plus souple
Marsh Posté le 16-11-2004 à 17:45:17
Tu peux filer une boost::function comme callback à une fonction C ?
Marsh Posté le 16-11-2004 à 18:01:21
HelloWorld a écrit : Y'a pas de solution portable, déjà à cause de l'asm. |
chui pas trop un mec qui se soucie de la portabilité
et ici y'a pu d'asm mais que des opcodes, donc c portable sur tout compatibl eintel x86
HelloWorld a écrit : |
bin oui
Marsh Posté le 16-11-2004 à 18:09:09
ReplyMarsh Posté le 16-11-2004 à 18:13:33
HelloWorld a écrit : Et les conventions d'appel ? |
comme dit dans le texte, __stdcall
pour __cdecl va falloir gruger un brin
Marsh Posté le 16-11-2004 à 18:16:14
tu ferais quand même mieux de typer plus fortement
Delegate(void *tThis, T fonction)
->
void Delegate(T * const that, void (T::*function)()
Marsh Posté le 16-11-2004 à 18:17:37
Taz a écrit : tu ferais quand même mieux de typer plus fortement |
c'etait un exemple vite torché, par contre je conteste le void de retour et mon template avait pas pour but de substituer au type de "this" mais a celui du ptr de fonction
Marsh Posté le 16-11-2004 à 18:31:43
HelloWorld a écrit : Tu peux filer une boost::function comme callback à une fonction C ? |
Je le fait toute la journée
Marsh Posté le 16-11-2004 à 19:03:50
t'es trop flemmard pour lire leur excellente documentation et leurs exemples ?
Marsh Posté le 16-11-2004 à 19:07:06
je trouve pas dans leur excellent exemple une excellente facon de mapper une excellente fonction membre sur une excellente callback type C. Mais faut dire que je suis excellement naze, la
Marsh Posté le 16-11-2004 à 19:13:02
ReplyMarsh Posté le 16-11-2004 à 20:26:32
Taz a écrit : mais les callback C, c'est naz ... |
oué d'accord, mais je sais pas si t'as vu, c'est un peu le but de ce bordel d'au dessus
Marsh Posté le 16-11-2004 à 20:29:28
mais dans une API C bien foutue, y a toujours un param supplémentaire void* data ...
Marsh Posté le 16-11-2004 à 20:30:48
Taz a écrit : mais dans une API C bien foutue, y a toujours un param supplémentaire void* data ... |
Certes, mais tu peux rapelle qu'une fonction public pour gerer la callback, alors
Marsh Posté le 16-11-2004 à 20:41:38
ReplyMarsh Posté le 16-11-2004 à 20:50:36
cela dit c'est vraiment du hack
quand tu fais du type-punning avec une union, techniquement, ton compilo à le droit d'optimiser et donc ça marcherait pas
Marsh Posté le 16-11-2004 à 20:52:10
Taz a écrit : cela dit c'est vraiment du hack |
Oui, mais comme tu vois, j'en suis pas un hack pres, alors si pour retrouver la valeur fo passer par un memcpy crado ou un coup d'asm inline, ca me fait pas peur (l'union marche tres bien, merci)
Marsh Posté le 16-11-2004 à 21:14:58
chrisbk a écrit : |
personnellement, je contourne le problème en déclarant la fonction en static
Marsh Posté le 16-11-2004 à 21:16:49
Harkonnen a écrit : personnellement, je contourne le problème en déclarant la fonction en static |
heuh, merci, hans
ca resouds pas tout hein ?
Marsh Posté le 16-11-2004 à 21:32:31
chrisbk a écrit : heuh, merci, hans |
ben non, le problème est que je ne peux plus accéder aux données membres non static de ma classe.
mais dans ce cas, je file en paramètre à la Callback le pointeur this, et j'appelle cette Callback à partir d'une fonction static (qui est en fait la vraie callback)
Marsh Posté le 16-11-2004 à 21:34:56
Harkonnen a écrit : ben non, le problème est que je ne peux plus accéder aux données membres non static de ma classe. |
methode taz de plus haut ca
mais spa tjs possible (genre les callback des fenetres windows. A part foutre dans le GWL_USERDATA en priant pour que personne vienne foutre sa merde, t'as une solution fine ?)
Marsh Posté le 16-11-2004 à 22:49:42
chrisbk a écrit : |
oui, je balance le this dans les propriétés des fenêtres, SetProp et GetProp roulaize
http://msdn.microsoft.com/library/ [...] erties.asp
edit: en plus, le GWL_USERDATA c'est le mal, car pour une fenêtre ou un controle que tu n'as pas créé toi même, tu peux pas être sur qu'il ne soit pas déja "occupé"
Marsh Posté le 16-11-2004 à 22:58:17
Poste inutile du gars qui se dit que ca doit etre bien de comprendre ce que vous racontez...le seul truc que g pigé parce que je le savais déjà, c qu'en static t'a pas accès aux variables d'instances (ce qui est la logique meme de la chose)...
Marsh Posté le 16-11-2004 à 23:18:29
Jubijub a écrit : Poste inutile du gars qui se dit que ca doit etre bien de comprendre ce que vous racontez...le seul truc que g pigé parce que je le savais déjà, c qu'en static t'a pas accès aux variables d'instances (ce qui est la logique meme de la chose)... |
bah, stout simple
la problématique est la suivante : une fonction callback est une fonction appelée par le système en réponse à un évènement précis. cette fonction doit respecter une certaine signature.
le problème avec le C++, c'est que chaque méthode de classe possède un premier argument caché : le pointeur de l'objet (le this). donc, la signature de la callback n'est pas respectée, et ça ne marche pas !
les seules fonctions C++ qui ne possèdent pas de this en 1er paramètres, sont les fonctions static. malheureusement, tu ne peux pas accéder aux données membres à partir des fonctions static.
d'où la bidouille du père bk (bidouille qui me rappelle certains hacks du temps ou je codais des démos, quand on se faisait chier à calculer des adresses relatives pour éviter de foutre en l'air le registre de pile, et pour gagner quelques cycles )
Marsh Posté le 16-11-2004 à 23:21:14
spa une bidouille, stun thunk
et ton compilo C++ t'en genere plein sans que tu le voyes
Marsh Posté le 16-11-2004 à 23:26:38
c'est pas ça du tout. les fonctions membres non-static ne sont tout simplement pas des fonctions comme les autres fonctions libres. Si y avait que cette histoire de this implicite, on se marrerait bien.
Marsh Posté le 16-11-2004 à 16:04:22
(y zy connaissent rien sur blabla, alors je m'adresse directement a l'elite)
Messieurs dames, bonjour, le cours du jour sera : comment faire des delegates en C++.
Le probleme que nous avons tous rencontré un jour, c'est une fonction demandant une Callback en entrée dans la main gauche, et une fonction membre qui serait parfaite pour ce role dans l'autre.
Drame : ca ne marche pas, car une fonction membre C++ demande en plus le 'this' de l'objet.
Que faire ? L'idéal serait un truc a la c#, un pointeur de fonction comprenant aussi le this, mais le tout sous forme d'unique pointeur de fonction. La technique decrite ici, que j'appelerais technique Colgate car j'ai eu l'idée en me brossant les dents, repond a ses attentes grace au "dynamic code generation" que j'ecris en anglais car l'anglais, ca pootre plus.
l'idée est d'intercaler entre un pointeur de fonction et la cible un code intermediaire servant a rebondir vers la cible. Ledit code intermediaire comprends simplement deux instructions asm fort banales : mov et jmp.
C'est tout.
Par convention le this est generalement foutu dans ecx, donc on le fait, et on fait un jmp a la place d'un call pour pas changer la pile. le jmp prends une valeur relative donc on la recalcule en live.
Le plus rigolo, c'est que, vive le C++, on peut tout balancer ca dans une...structure, sans toucher du tout a l'asm, ou peu.
et voila le travail.
le probleme est de retrouver l'adresse de la fonction membre sous forme de void *, taz avait refilé une interessante solution a coup d'union. On peut meme rajouter une couche de template par dessus, et la, vla le bonheur :
Pour ensuite utiliser ca comme callback, il suffit de caster l'adresse de cette structure en pointeur de fonction (si, si) et vala.
enfin j'ai pas encore essayé mais ca devrait marcher au poil.
Notez le stdcall. De nombreuses api sont en cdcel, et pas en stdcall, ce qui necessitera un peu de réecriture au niveau du code (passage du mov en autre chose). Je laisse ca en exerice pour le lecteur
merci de votre attention
---------------
NP: HTTP Error 764 Stupid coder found