You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.9 KiB
154 lines
5.9 KiB
/**
|
|
* \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);
|
|
}
|