This is old C++ code originally intended to be a playground for 3D math.
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

/**
* \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);
}