16,471
社区成员
发帖
与我相关
我的任务
分享
#include "stdafx.h"
typedef unsigned int DWORD;
//取类成员函数的地址.vc8版本.可以取私有成员函数地址.
#define GetMemberFuncAddr_VC8(FuncAddr,FuncType)\
{ \
__asm \
{ \
mov eax,offset FuncType \
}; \
__asm \
{ \
mov FuncAddr, eax \
}; \
}
//取类成员函数的地址.vc6版本.
template <class ToType, class FromType>
void GetMemberFuncAddr_VC6(ToType& addr,FromType f)
{
union
{
FromType _f;
ToType _t;
}ut;
ut._f = f;
addr = ut._t;
}
//调用类成员函数
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; //call 1.向堆栈中压入下一行程序的地址;2.JMP到call的子程序地址处。
mov re,eax;
}
return re;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void test1()//演示c++成员函数指针的用法.
{
class tt
{
public: void foo(int x){ printf("\n %d \n",x); }
};
typedef void (tt::* FUNCTYPE)(int);
FUNCTYPE ptr = &tt::foo; //给一个成员函数指针赋值.
tt a;
(a.*ptr)(5); //调用成员函数指针.
tt *b = new tt;
(b->*ptr)(6); //调用成员函数指针.
delete b;
// DWORD dwFooAddrPtr= 0;
// dwFooAddrPtr = (DWORD) &tt::foo; /* Error C2440 */
// dwFooAddrPtr = reinterpret_cast<DWORD> (&tt::foo); /* Error C2440 */
}
void test2()//示范如何取成员函数地址.
{
class tt
{
public: void foo(int x){ printf("\n %d \n",x); }
};
#if _MSC_VER >1200
DWORD dwAddrPtr1;
GetMemberFuncAddr_VC8(dwAddrPtr1,tt::foo);
printf("\n test2 tt::foo %08x",dwAddrPtr1);
#endif
DWORD dwAddrPtr2;
GetMemberFuncAddr_VC6(dwAddrPtr2,&tt::foo);
printf("\n test2 tt::foo %08x",dwAddrPtr2);
}
void test3()//示范如何调用成员函数地址.
{
class tt
{
public:
void foo(int x,char c,char *s)//没有指定类型,默认是__thiscall.
{
printf("\n m_a=%d, %d,%c,%s\n",m_a,x,c,s);
}
void __stdcall foo2(int x,char c,char *s)//成员函数指定了__stdcall调用约定.
{
printf("\n m_a=%d, %d,%c,%s\n",m_a,x,c,s);
}
int m_a;
};
typedef void (__stdcall *FUNCTYPE) ( int,char,char*);//定义对应的非成员函数指针类型,注意指定__stdcall.
typedef void (__stdcall *FUNCTYPE2)(void *,int,char,char*);//注意多了一个void *参数.
tt abc;
abc.m_a = 123;
DWORD ptr;
DWORD This = (DWORD)&abc;
GetMemberFuncAddr_VC6(ptr,&tt::foo); //取成员函数地址.
FUNCTYPE fnFooPtr = (FUNCTYPE) ptr;//将函数地址转化为普通函数的指针.
__asm //准备this指针.
{
mov ecx, This;
}
fnFooPtr(5,'a',"7xyz"); //象普通函数一样调用成员函数的地址.
GetMemberFuncAddr_VC6(ptr,&tt::foo2); //取成员函数地址.
FUNCTYPE2 fnFooPtr2 = (FUNCTYPE2) ptr;//将函数地址转化为普通函数的指针.
fnFooPtr2(&abc,5,'a',"7xyz"); //象普通函数一样调用成员函数的地址,注意第一个参数是this指针.
}
void test4()//示范通过CallMemberFunc调用成员函数
{
class tt
{
public:
void foo(int x,char c,char *s)//没有指定类型,默认是__thiscall.
{
printf("\n m_a=%d, %d,%c,%s\n",m_a,x,c,s);
}
void __stdcall foo2(int x,char c,char *s)//成员函数指定了__stdcall调用约定.
{
printf("\n m_a=%d, %d,%c,%s\n",m_a,x,c,s);
}
int m_a;
};
tt abc;
abc.m_a = 123;
DWORD ptr1,ptr2;
GetMemberFuncAddr_VC6(ptr1,&tt::foo); //取成员函数地址.
GetMemberFuncAddr_VC6(ptr2,&tt::foo2); //取成员函数地址.
CallMemberFunc(0,ptr1,&abc,3,5,'a',"7xyz");//第一个参数0,表示采用__thiscall调用.
CallMemberFunc(1,ptr2,&abc,3,5,'a',"7xyz");//第一个参数1,表示采用非__thiscall调用.
}
void test5()//示范在继承情况下使用函数地址.
{
class tt1
{
public:
void foo1(){ printf("\n hi, i am in tt1::foo1\n"); }
virtual void foo3(){ printf("\n hi, i am in tt1::foo3\n"); }
};
class tt2 : public tt1
{
public:
void foo2(){ printf("\n hi, i am in tt2::foo2\n"); }
virtual void foo3(){ printf("\n hi, i am in tt2::foo3\n"); }
};
DWORD tt1_foo3,tt2_foo1,tt2_foo2,tt2_foo3;
GetMemberFuncAddr_VC6(tt1_foo3,&tt1::foo3);
GetMemberFuncAddr_VC6(tt2_foo1,&tt2::foo1);
GetMemberFuncAddr_VC6(tt2_foo2,&tt2::foo2);
GetMemberFuncAddr_VC6(tt2_foo3,&tt2::foo3);
tt1 x;
tt2 y;
CallMemberFunc(0,tt1_foo3,&x,0); // tt1::foo3
CallMemberFunc(0,tt2_foo1,&x,0); // tt2::foo1 = tt1::foo1
CallMemberFunc(0,tt2_foo2,&x,0); // tt2::foo2
CallMemberFunc(0,tt2_foo3,&x,0); // tt2::foo3
CallMemberFunc(0,tt1_foo3,&y,0); // tt1::foo3
CallMemberFunc(0,tt2_foo1,&y,0); // tt2::foo1 = tt1::foo1
CallMemberFunc(0,tt2_foo2,&y,0); // tt2::foo2
CallMemberFunc(0,tt2_foo3,&y,0); // tt2::foo3
}
int main(int argc, char* argv[])
{
test1();
test2();
test3();
test4();
test5();
return 0;
}