首先咱们须要搞清楚一个问题,为何咱们要用Thunk技术?Thunk技术能够解决神马难题?html
在探寻上面的问题以前先讲述一下线程从面向过程到面相对象编程所面临的问题和解决的方法,由于Thunk也是为了解决这些问题而产生的c++
咱们知道用Window的API来开发程序的话其实是用的C语言的面向过程的方式来开发的。编程
而在咱们使用C++开发程序的时候一般都是用的OOP(面向对象编程)的方式来编写的。函数
例如在C语言里面建立线程时是直接用_beginthread()一条函数就 能够的了,而在c++里面咱们一般想要封装成一个线程类。ui
来看看线程是怎么转变的?先看下_beginthread()的声名this
uintptr_t _beginthread( void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist);
_beginthread()的第一个参数说明了咱们要建立线程就须要定义一个像下面这样格式的函数线程
void ThreadFunc(void* pVoid);
在C的面相过程的编程方式中实际上这个函数是一个裸露在外的全局函数,若是咱们要将它封装到类里面怎么作呢?咱们最直接的想法是这样作指针
class MyClass { public: void StartThread() { _beginthread(ThreadFunc, NULL, NULL); } ... void ThreadFunc(void* pVoid); ... }
可是实际上这样会编译错误的,由于ThreadFunc做为成员函数会被编译器编译为这样的格式,致使在编译的时候参数不一致code
void MyClass::ThreadFunc(this, void* pVoid)
成员函数会被加上this指针,若是不知道为何就百度一下编译器编译成员函数的方法吧。。。htm
那么是否是ThreadFunc没办法放在类里面了呢?有没有解决办法呢?有的,只要把ThreadFunc声名为类的静态成员函数就能够了,由于被声名为static的函数是不会被在参数列表里面加上this指针的。因而修改以下
class MyClass { public: void StartThread() { _beginthread(ThreadFunc, NULL, NULL); } ... static void ThreadFunc(void* pVoid); ... }
可是这样的话问题又来了,咱们知道静态成员函数其实是不属于类的任何对象的,也就是静态函数没法访问类对象的成员变量,由于它没有this指针。
这是个很是糟糕的状况啊,由于咱们的线程一般都要访问类对象的成员变量的(总要存取某些值之类的吧),那么咱们是否是能够尝试把this指针传递给静态函数ThreadFunc呢?这样咱们就能用这个this指针作普通成员函数作的事情了。
咱们注意到ThreadFunc(void* pVoid)是有个void类型的指针的参数传入的,从字面意思是能够传入任意的指针的。那么咱们就从这个入手,咱们把this指针用这个pVoid参数传入进去。再在ThreadFunc内部转换一下指针类型就大功告成了。
再往上看一下_beginthread()的声名,发现最后一个参数实际上就是会传递给ThreadFunc的void参数的。咱们这样作就能够了
class MyClass { public: void StartThread() { _beginthread(ThreadFunc, NULL, this); } ... void ThreadFunc(void* pVoid); ... }
线程从面向过程到面向对象的转变有些曲折,可是总归是顺利的利用pVoid这个预留的参数解决了
后续继续讨论Thunk是如何实现的