直接调用类成员函数地址
2010-07-25 20:45:42 来源:WEB开发网每次都定义一个函数类型并且进行一次强制转化,这个事是比较烦的,能不能将这些操作写成一个函数,然后每次调用是指定函数地址和参数就可以了呢?当然是可以的,并且我已经写了一个这样的函数。
//调用类成员函数
使用这个函数,则上面的两个调用可以这样写:
//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参数也是不行的。
总结一下,如果成员函数的参数都是整型兼容类型,则可以使用CallMemberFunc调用函数地址。如果不是,那就只有按前面的方法,先定义对应的普通函数类型,强制转化,准备this指针,然后调用普通函数指针。
更多精彩
赞助商链接