"Klaus Petersen" <ng@spectual.ra.bnaa.dk> wrote in message 
news:4198f4e8$0$33740$14726298@news.sunsite.dk...
>> Der findes en mere avancerede måde, hvor call-thunken bliver lave 
>> dynamisk
>> på runtime - men det kan typisk ikke svare sig.
>
> Kender du metoden?
Ja.
Den er dog mere relevant i forbindelse på steder hvor der ikke kan føre en 
void pointer med, og hvor man ofte skal lave en mapning fra en funktion til 
et objekt.
Det er f.eks. anvendt i flere biblioteker hvor man har lavet en 
objekt-orienteret indpakning af vinduer til MS-Windows (bl.a. Borland OWL og 
Microsoft WTL).
Her vil man sende en Window message til et objekt - gerne i konstant, kort 
tid.
> Den kunne jeg godt tænke mig at høre mere om.
Man allokerer et stykke hukommelse, som man fylder med passende op-koder 
(assembler instruktioner) og gemmer passende ekstra information sammen med 
koden.
Den funktion (f.eks. CreateThread) som kræver adressen på en call-back 
metode får så bare en adresse til det netop allokerede og initialiserede 
hukommelse.
Altså man laver simpelt hen en funktion pr. objekt på runtime 
Nedenstående er noget kode jeg har skrevet for en del år siden, der kunne 
mappe fra WNDPROC til et "Window" objekt.
Det er ikke let læseligt - men effektivt 
// This structure _must_ be packed
#if defined(__BORLANDC__) && (0x0564 == __BORLANDC__)
// Borland C++Builder V6.0
#pragma option push -a1
#elif defined(__INTEL_COMPILER) && (500 == __INTEL_COMPILER || 600 == 
__INTEL_COMPILER || 700 == __INTEL_COMPILER) && defined(_WIN32)
// Intel C++ for Windows V5.0, V6.0 or V7.x
#pragma pack(push, 1)
#elif defined(_MSC_VER)
// Microsoft Visual C++V7.1 (.NET 2003)
#pragma pack(push, 1)
#endif
class InstanceThunk
{
public:
   InstanceThunk(Window* wnd, WNDPROC wndproc)
   {
      call   = 0xE8u;      // CALL rel32
#if defined(__BORLANDC__) && (0x0564 == __BORLANDC__)
// Borland C++Builder V6.0
      offset = offsetof(InstanceThunk, code) - offsetof(InstanceThunk, 
proc);
#elif (defined(__INTEL_COMPILER) && (500 == __INTEL_COMPILER || 600 == 
__INTEL_COMPILER || 600 == __INTEL_COMPILER) && defined(_WIN32)) || 
defined(__COMO__)
// Intel C++ for Windows V5.0, V6.0 or V7.1
// Comeau C++ for Windows
// offsetof is not supported by Intel C++
      offset = 8; //offsetof(InstanceThunk, code) - offsetof(InstanceThunk, 
proc);
#elif (defined(_MSC_VER))
// Microsoft Visual C++ 7.1 (.NET 2003)
      offset = 8; //offsetof(InstanceThunk, code) - offsetof(InstanceThunk, 
proc);
#endif
      proc   = wndproc;
      window = wnd;
      // POP ECX
      //
      // Pop return address of call into ecx (address of member "proc")
      //
      code[0] = 0x59u;
      // MOV EDX, [ECX+4]
      //
      // load "window" into edx
      //
      code[1] = 0x8B;
      code[2] = 0x51u;
      code[3] = 0x04u;
      // JMP [ECX]
      //
      // jump to window function provided
      code[4] = 0xFFu;
      code[5] = 0x21u;
   }
   WNDPROC  WndProc()
   {
      return reinterpret_cast<WNDPROC>(this);
   }
private:
   unsigned char     call;
   int               offset;
   WNDPROC           proc;
   Window*      window;
   unsigned char     code[6];
private:
   InstanceThunk(const InstanceThunk&);
   InstanceThunk& operator=(const InstanceThunk&);
};
#if defined(__BORLANDC__) && (0x0564 == __BORLANDC__)
// Borland C++Builder V6.0
#pragma option pop
#elif defined(__INTEL_COMPILER) && (500 == __INTEL_COMPILER || 600 == 
__INTEL_COMPILER || 700 == __INTEL_COMPILER) && defined(_WIN32)
// Intel C++ for Windows V5.0, V6.0 og V7.x
#pragma pack(pop)
#elif defined(_MSC_VER)
// Microsoft Visual C++V7.1 (.NET 2003)
#pragma pack(pop)
#endif
Venlig hilsen
Mogens Hansen