通用 Thunk
2008-05-25 21:39:20 来源:WEB开发网更多详细信息 见 Thunk.h和 示例(sample)工程(project)
示例工程包含5个程序的源代码,但是没有可执行文件,否则会太庞大。工程可以在Visual Studio 2005上顺利编译,只要工程的目录结构维持原样。5个程序使用一份相同的测试代码——TestClass.h TestClass.cpp main.cpp。不同之处在预处理器的定义。这样,它们分别测试了 ThisToStd,ThisToCdecl,StdToStd,StdToCdecl和CdeclToCdecl的功能。除了这些,你还可以从中得知使用一个Thunk类,需要包含和加入到工程中的最少文件。(只包含Thunk.h 并把Thunk.cpp 加入工程中也能工作,但不是最好方法)
原理
原理中最重要的是函数的调用约定(Calling Convention) ,调用者和被调者之间的约定。普通C函数通常使用3种调用约定 : “__cdecl” “__stdcall” “__fastcall” 成员函数通常使用 “__thiscall””__stdcall” “__cdecl”
我们需要着重关注以下3点:
调用者(普通C函数)怎么准备参数和返回地址?
被调用者(成员函数)希望并且要求的参数和返回地址是什么?它如何取得它们?
平衡堆栈是谁的责任?
调用者准备的参数和返回地址总不是被调用者所期待的那样,因为被调用者还需要一个this指针。平衡堆栈的方式也许也会不同。我们的工作就是以被调用者期望的方式,准备好this指针,同时弥补2者在平衡堆栈上的差异。
为了简单起见,我们以 “ void func(int); void C::func(int); ”为例,首先,我们来看看当使用__stdcall 约定的func被调用的时候,会发生什么。
func(1212); 编译器会像这样准备参数和返回地址 :
更多精彩
赞助商链接