// Klasse, um an eine Rückrufadresse eine benutzerspezifische Adresse
// zu liefern; Anwendungsbeispiel siehe unten - h#s 12/05
#ifndef THUNK_H
#define THUNK_H
#include <windows.h> // Datentypen (sonst nicht notwendig)
#ifdef _M_IX86
# define THUNK_CODESIZE 12 // Code-Größe ist plattformabhängig!
#else
# error Nicht unterstützte Plattform! Ggf. Kode hier einfügen!
#endif
class CThunk {
public:
MakeCdecl (LPVOID FuncPtr, PVOID Arg); // für cdecl-Funktionen
MakeStdcall(LPVOID FuncPtr, PVOID Arg); // für stdcall-Funktionen
private:
BYTE code[THUNK_CODESIZE];
};
/* Zweck:
* Es kommt immer wieder vor, dass es Rückruffunktionen ohne
* frei verwendbaren Hilfsparameter gibt.
* Dann ist es bei Verwendung mehrerer Daten-Instanzen nicht mehr
* möglich, zwischen "Objekt A" und "Objekt B" zu unterscheiden,
* außer über eine globale Variable. Dann ist's nicht mehr multi-
* thread-sicher. Da hilft bloß noch eine thread-lokale Variable.
*
* Sofern jedoch wenigstens die Rückrufadresse frei wählbar ist,
* kann diese auf dynamisch erzeugten Kode zeigen, welche den
* Zusatzparameter nachreicht. Ein Thunk eben.
* Geeignet für alle von-Neumann-Prozessorarchitekturen.
*/
/****************************************************************
* Verwendung: Beispiel qsort: *
* *
* // Nicht-Memberfunktion (Freund von CBeispiel): *
* static int _cdecl CompFunc( *
* CBeispiel* obj, LPVOID, void*left, void*right) { *
* return obj->Vergleich(left,right) *
* } *
* *
* // Beispiel-Klasse *
* class CBeispiel { *
* friend int _cdecl CompFunc(CExample*,LPVOID,void*,void*); *
* CThunk m_cThunk; *
* CBeispiel() {m_cThunk.MakeCdecl(CompFunc, this);} *
* int Vergleich(void*left, void*right) {return ...;} *
* void Sortiere() {qsort(...Array, ...Size, &m_cThunk);} *
* } *
****************************************************************/
/* Verwendung (allgemein):
* Mit MakeCdecl() wird das CThunk-Objekt mit Kode gefüllt, welches
* eine Funktion mit der gleichen Signatur aufruft wie ohne Thunk,
* mit zwei zusätzlichen Parametern am Anfang:
* -> 1. Parameter = übergebener Parameter
* -> 2. Parameter = (fest) LPVOID; dieser darf nicht angerührt werden!
* Die Funktion muss mit _cdecl deklariert werden!
*
* Mit MakeStdcall() wird das CThunk-Objekt mit Kode gefüllt, welches
* eine Funktion mit der gleichen Signatur aufruft wie ohne Thunk,
* mit einem zusätzlichen Parameter am Anfang:
* -> 1. Parameter = übergebener Parameter
* Die Funktion muss mit _stdcall deklariert werden!
*
* Mit MakeStdcall() können auch _pascal-Funktionen angesprungen werden,
* sofern vom Compiler unterstützt. Der Extra-Parameter erscheint
* als letzter Parameter.
*
* Es gibt hier kein MakeFastcall() - eine solche Aufrufkonvention ist
* nicht allgemein festgelegt.
*
* Weil bei (nicht-statischen) Memberfunktionen der this-Zeiger als erstes
* übergeben wird, sollte auch der direkte Aufruf von Objektfunktionen
* möglich sein; dies ist ungetestet.
* Der Aufruf einer virtuellen Funktion ist dabei nicht direkt möglich.
*/
#endif
Vorgefundene Kodierung: ANSI (CP1252) | 4
|
|