這一篇文章中主要是講解怎麼寫代碼把以上3篇文章的理論用起來,寫出一個能用的Thread類(只是模型)
我在第3篇中提到了,要想把類的成員函數做Thread函數,一定要在一個時候把this指標賦值給ecx,問題是在類的成員函數裡面是不太可能做這種事情的,因為如果你要讓fun成為線程函數,你就需要在別的函數裡面初始化ecx,這樣感覺有點多餘。我用的最簡單的一個方法是寫一段機器代碼,在這個機器代碼裡面完成所有的工作:初始化ecx,跳轉到fun函數………至於那段機器代碼怎麼來的我想,我們用Vs調試的時候有個顯示機器代碼的選項,可以用這個看到吧,呵呵。不說了,下面直接放代碼。
//core.h#ifndef __ZX_CORE_H__#define __ZX_CORE_H__#include <windows.h>#ifndef interface#define interface struct#endif#ifndef implement#define implement :public#endifconst static unsigned charg_thread_proc[]={//------------parameter-----------------0x8B,0x44,0x24,0x04,// mov eax,dword ptr [esp+10h] 0x50,// push eax //-----------this pointer-------------0xB9,0x00,0x00,0x00,0x00, // mov ecx,0x12FF5C //-----------call back function-------------0xB8,0x00,0x00,0x00,0x00, // mov eax,0 0xFF,0xD0,// call eax//return0xC2,0x10,0x00// ret 10h };#endif
//runnable.h#ifndef__ZX_RUNNABLE_H__#define __ZX_RUNNABLE_H__#include "core.h"interface ZXRunnable{virtual void run(void* lpParameter)= 0;};#endif
//thread.h#ifndef __ZX_THREAD_H__#define __ZX_THREAD_H__#include "core.h"#include "runnable.h"class ZXThread{public:ZXThread();ZXThread(ZXRunnable* runnable);virtual ~ZXThread();public:void Start();void Wait();void SetRunnable(ZXRunnable* runnable);ZXRunnable* GetRunnable();private:ZXRunnable*m_pRunnable;HANDLEm_hThread;unsigned char m_thread_proc[sizeof(g_thread_proc)];};#endif
//thread.cpp#include "thread.h"ZXThread::ZXThread(): m_pRunnable(NULL), m_hThread(NULL){}ZXThread::ZXThread(ZXRunnable* runnable): m_pRunnable(runnable), m_hThread(NULL){}ZXThread::~ZXThread(){delete m_pRunnable;}void ZXThread::SetRunnable(ZXRunnable* runnable){m_pRunnable=runnable;}ZXRunnable* ZXThread::GetRunnable(){return(m_pRunnable);}void ZXThread::Start(){CopyMemory(m_thread_proc, g_thread_proc, sizeof(g_thread_proc));*(int*)(&m_thread_proc[6])= (int)m_pRunnable;void (ZXRunnable::*func)(void* lpParameter)= &ZXRunnable::run;int addr;__asm{mov eax, funcmov addr, eax}*(int*)(&m_thread_proc[11])= addr;m_hThread= ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(void*)m_thread_proc, NULL, 0, NULL);}void ZXThread::Wait(){::WaitForSingleObject(m_hThread, INFINITE);}
以下就是測試案例了哦:
#include <iostream>#include "thread.h"using namespace std;class ZXRun implement ZXRunnable{public:virtual void run(void* lpParameter){cout<<"Hello,World!"<<endl;}};int main(){ZXThread boss(new ZXRun);boss.Start();boss.Wait();}
注意,這個代碼可能會崩潰,因為我們讓資料當指令執行,因此需要關閉DEP,關閉DEP的方法參見網址:http://www.baidu.com/s?ie=utf-8&bs=VS%E5%85%B3%E9%97%ADDEP&f=8&rsv_bp=1&rsv_spt=3&wd=Visual+Studio%E5%85%B3%E9%97%ADDEP&inputT=2696
其步驟也比較簡單:開啟工程屬性(不是解決方案屬性哦)->Linker->Advanced->Data execution prevention(後面選擇NO)。
至此,全部過程完成。