什么是thunk技术实现?


/************************ Copyright (c) 2013 ************************


功能描述:

    thunk技术实现.利用这个类可以把回调函数完全封装成类成员函数.

调用示例:

 //导入头文件及库文件
 #include "ZThunk.h"

 class CTimer
 {
 private:

  // 此对像必须声时为类的数据成员或者全局对像,以保证它的生命周期
  ZThunk m_thunk;

 public:
  
  //安装定时器
  void Set()
  {
   //计算回调函数地址
   void* pAddr=m_thunk.Callback(this,&CTimer::TimerProc,ZThunk::THISCALL);

   // 此为安装定器函数的原形
   // UINT_PTR SetTimer(
   // HWND hWnd,              // 窗口句柄
   // UINT_PTR nIDEvent,      // 定时器ID
   // UINT uElapse,           // 时间间隔
   // TIMERPROC lpTimerFunc   // 定时器回调函数
   
   //安装计时器
   SetTimer(NULL,1,1000,(TIMERPROC)pAddr); 
  }

  //定时器回调函数,完全被封装成类成员函数!
  void TimerProc(HWND hWnd, DWORD dwMsg , WPARAM wPa, LPARAM lPa)
  {
   // to do something
  }
 };

************************ Copyright (c) 2006 ************************/
/*
网络上流行的Thunk技术,主要用于将成员函数变为线程函数或窗口过程.
弥补了static成员函数不能访问非静态成员数据的缺点,
最典型的应用就是微软的MFC和ATL中的窗口类实现,此原码也是网上公开的一个Thunk类
*/

#ifndef _ZTHUNK
#define _ZTHUNK

class ZThunk 
{
private:
 unsigned char m_ThiscallCode[10];
 unsigned char m_StdcallCode[16];
public:
 enum CALLINGCONVENTIONS
 {
  STDCALL = 1,
  THISCALL= 2
 };
public:
 template <class T>
 void* Callback(void* pThis,T MemberOffset,CALLINGCONVENTIONS CallingConvention = STDCALL)
 {
  // these codes only use in stdcall
  if(CallingConvention == STDCALL)
  {
   // Encoded machine instruction   Equivalent assembly languate notation
   // ---------------------------   -------------------------------------
   // FF 34 24                      push  dword ptr [esp]          ; Save (or duplicate)                                                                    ; the Return Addr into stack
   // C7 44 24 04 ?? ?? ?? ??       mov   dword ptr [esp+4], pThis ; Overwite the old                                                                    ; Return Addr with 'this pointer'
   // E9 ?? ?? ?? ??                jmp   target addr              ; Jump to target message handler

   char Buf[33]={0};
   sprintf(Buf,"%d",MemberOffset);
   unsigned long JmpAddr = (unsigned long) atol(Buf) - (unsigned long) &m_StdcallCode[0] - 16;

   m_StdcallCode[11] = 0xE9;
   *((unsigned long *)  &m_StdcallCode[ 0]) = 0x002434FF;
   *((unsigned long *)  &m_StdcallCode[ 3]) = 0x042444C7;
   *((unsigned long *)  &m_StdcallCode[ 7]) = (unsigned long) pThis;
   *((unsigned long *)  &m_StdcallCode[12]) = JmpAddr;

   return (void*)m_StdcallCode;
  }
  // these codes only use in thiscall
  else if(CallingConvention == THISCALL)
  {
   // Encoded machine instruction   Equivalent assembly languate notation
   // ---------------------------   -------------------------------------
   // B9 ?? ?? ?? ??                mov    ecx, pThis  ; Load ecx with this pointer
   // E9 ?? ?? ?? ??                jmp    target addr ; Jump to target message handler

   char Buf[33]={0};
   sprintf(Buf,"%d",MemberOffset);
   unsigned long JmpAddr = (unsigned long) atol(Buf) - (unsigned long) &m_ThiscallCode[0] - 10;

   m_ThiscallCode[0] = 0xB9;
   m_ThiscallCode[5] = 0xE9;
   *((unsigned long *) &m_ThiscallCode[1]) = (unsigned long) pThis;
   *((unsigned long *) &m_ThiscallCode[6]) = JmpAddr;

   return (void*)m_ThiscallCode;
  }return 0;
 }
};

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值