callback.h
5.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* \file callback.h
*
* \brief Implementiert callbacks aus Membern und Funktionen.
*
* Enthält alle nötigen Klassen, um sowohl aus Klassenmembern
* als auch aus normalen Funktionen Callbacks zu machen. Das heißt
* das sowohl die Adresse des Objekts als auch die der Methode/Funktion
* gespeichert wird und bei bedarf richtig aufgerufen wird. Es lassen sich
* also Methoden in Arrays oder Listen vorhalten.
*
* \author Georg Steffers <georg@steffers.org>
*
* \date 04.12.2003
*
* \version ..2001 (Georg Steffers): erste implementation
* \version 2001-2003 (Georg Steffers): diverse Modifikationen
* \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen
*/
/*
* Copyright (C)2003 Georg Steffers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
using namespace std;
#include <cstring>
// enthaelt die adressen unserer callbackfunktion bzw. der Klasse und des
// Members die wir aufrufen moechten....(dies hier ist die Basisklasse
// diese wird gleich spezifiziert
class FunctorBase {
public:
// dient wohl nur dazu die groesse eines Member-Pointers zu bestimmen.
typedef void (FunctorBase::*t_MemberFunc)();
// hierdrin wird der Quatsch gespeichert....
union {
const void* Callback;
char CallbackMember[sizeof(t_MemberFunc)];
};
void* Class;
// Konstruktoren
// wichtig, wenn ein Object der Klasse FunctorBase oder einer
// abgeleiteten Klasse kopiert werden soll.
FunctorBase() : Class(0), Callback(0) {}
// Hiermit wird eine FunctorBase angelegt.
FunctorBase(const void* _Class, const void* _Callback, size_t Size) {
if(_Class) { //Mit nem Member initialisiert
Class=(void*)_Class;
memcpy(CallbackMember, _Callback, Size);
}
else { // Mit ner normalen Funktion initialisiert
Class=NULL;
Callback=_Callback;
}
}
};
// dies wird nu ein Functor, der einen Callback aufnehmen kann, der einen
// beliebiegen Parameter hat und void zurueckgibt.
template <class P1, class P2>
class callback : protected FunctorBase {
// wir machen einen protected Konstruktor fuer die Klasse, damit nur
// abgeleitete Klassen einen callback erzeugen koennen. Diese mussen dann
// sicherstellen, das Funktor1 nur mit Methoden oder Funktionen erzeugt
// wird, die genau einen Parameter akzeptieren und void zurueckliefern.
// Der Teil RestoreTypeAndCall(_RTAC) initialisiert RestoreTypeAndCall
// auf _RTAC.
protected:
typedef void (*t_RestoreTypeAndCall)(const FunctorBase&, P1, P2);
callback(t_RestoreTypeAndCall _RTAC, const void *_Class,
const void *_Callback, size_t _Size) :
FunctorBase (_Class, _Callback, _Size), RestoreTypeAndCall(_RTAC) {}
private:
t_RestoreTypeAndCall RestoreTypeAndCall;
public:
callback() {}
void operator() (P1 p1, P2 p2) const { // ueber den koennen wir nachher
// den Callback aufrufen.
if(Class) // Wir haben nen Member...
RestoreTypeAndCall(*this, p1, p2);
else // normale Funktion, koennen wir direkt aufrufen...
((void (*)(P1,P2))Callback)(p1, p2);
}
const void* getcb(void) { return Callback; }
int is_null(void) {
if(Class != 0 || Callback != 0)
return false;
return true;
}
};
// beim speichern der Klasse als void* ist uns der Typ der Klasse und
// auch das eigentliche Object verloren gegangen.
// Deshalb kommt hier jetzt ne Klasse, die den Typ kennt und
// bei bedarf (jedesmal wenn eine Memberfunktion als Callback aufgerufen
// werden soll) zurueckwandelt.
// Ein template: Callee ist jede beliebige Klasse und Func jeder Member
template <class Callee, class Func, class P1, class P2>
class MemberTranslator : public callback<P1,P2> {
public:
MemberTranslator(Callee &Class, const Func &MemberFunction) :
callback<P1,P2>(RestoreTypeAndCall, &Class, &MemberFunction,
sizeof(Func)) {}
static void RestoreTypeAndCall(const FunctorBase &ftor, P1 p1, P2 p2) {
Callee* Who = (Callee*)(ftor.Class);
Func TheMemberFunction=*(Func*)(void*)(ftor.CallbackMember);
(Who->*TheMemberFunction)(p1, p2);
}
};
// Da der Konstruktor von callback protected ist brauchen wir noch einen
// Translator um aus normalen Funktionen Callbacks zu machen.
template <class P1, class P2>
class FunctionTranslator : public callback<P1,P2> {
public:
FunctionTranslator(void *regularFunc) :
callback<P1,P2>(NULL,NULL,regularFunc,0) {}
};
// und jetzt noch 2 makeCallback Templates um das erstellen von Callbacks zu
// erleichtern.
template <class Callee, class P1, class P2>
callback<P1, P2> mk_callback(Callee &Class, void (Callee::*Member)(P1, P2)) {
return MemberTranslator<Callee,void (Callee::*)(P1,P2),P1,P2>(Class,
Member);
}
template <class P1, class P2>
callback<P1, P2> mk_callback(void (*theFunc)(P1, P2)) {
return FunctionTranslator<P1, P2>((void*)theFunc);
}