直接调用类成员函数地址

http://tech.ddvip.com   2008年03月27日    社区交流

内容摘要:介绍了如何取成员函数的地址以及调用该地址.

//调用类成员函数
//callflag:成员函数调用约定类型,0--thiscall,非0--其它类型.
//funcaddr:成员函数地址.
//This:类对象的地址.
//count:成员函数参数个数.
//...:成员函数的参数列表.
DWORD CallMemberFunc(int callflag,DWORD funcaddr,void *This,int count,...)
{
  DWORD re;
  if(count>0)//有参数,将参数压入栈.
  {
    __asm
    {
      mov ecx,count;//参数个数,ecx,循环计数器.
      mov edx,ecx;
      shl edx,2;  
      add edx,0x14; edx = count*4+0x14;
   next:  push dword ptr[ebp+edx];
      sub  edx,0x4;
      dec  ecx 
      jnz  next;
    }
  }
  //处理this指针.
  if(callflag==0) //__thiscall,vc默认的成员函数调用类型.
  {
    __asm mov ecx,This;
  }
  else//__stdcall
  {
    __asm push This;
  }
  __asm//调用函数
  {
    call funcaddr;
    mov re,eax;
  }
  return re;
}
使用这个函数,则上面的两个调用可以这样写:

  CallMemberFunc(0,ptr1,&abc,3,5,'a',"7xyz");//第一个参数0,表示采用__thiscall调用.

  CallMemberFunc(1,ptr2,&abc,3,5,'a',"7xyz");//第一个参数1,表示采用非__thiscall调用.

  需要说明的是,CallMemberFunc是有很多限制的,它并不能对所有的情况都产生正确的调用序列。原因之一是它假定每个参数都使用了4个字节的栈空间。这在大多数情况下是正确的,比如参数为指针,char,short,int,long以及对应的无符号类型,这些参数确实都是每一个参数使用了4字节的栈空间。但是还有很多情况下,参数不使用4字栈空间,比如double,自定义的结构或类.float虽然是占了4字节,但编译器还产生了一些浮点指令,而这些无法在CallMemberFunc被模拟出来,因此对float参数也是不行的。

来源:vckbase    作者:南风    责编:豆豆技术应用

正在加载评论...