Source file: /~heha/hsn/thunk.zip/Thunk.h

// 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
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded