class a{
public:
void check(void * param)
{
MessageBox(NULL,"a","a",0);
}
void run()
{
_begindthread(check,NULL,NULL);
}
}
为什么我这样调用不了?请问一下有别的好的解决方案吗?能够提供示例代码最好。先谢谢了。
8 个解决方案
#1
请google之。
#2
这是我发的支持x64平台的thunk例子:
http://download.csdn.net/source/1137001
更多的thunk资源下载: http://search.download.csdn.net/search/thunk
更多的thunk资源下载: http://search.download.csdn.net/search/thunk
#3
起类方法线程, static, _beginthread最好加上ex.
#4
这里的文章及源码都很精彩:
http://www.vckbase.com/document/finddoc.asp?keyword=thunk
thunk在ATL中得到广泛应用。
这是我写过的thunk封装。
thunk在ATL中得到广泛应用。
这是我写过的thunk封装。
/*
* Copyright (C) QPSOFT.COM All rights reserved.
*/
#pragma once
namespace qp
{
#if defined(_M_IX86)
#define THUNK_CODE_LENGTH_WNDPROC 27
#define THUNK_CODE_LENGTH_GENERAL 10
#elif defined(_M_AMD64)
#define THUNK_CODE_LENGTH_WNDPROC 35
#define THUNK_CODE_LENGTH_GENERAL 31
#endif
#pragma optimize("", off)
#pragma push_macro("new")
#undef new
#pragma pack(push,1)
// 必须使用__stdcall调用约定
struct WndProcData
{
void* Init(DWORD_PTR proc, void* thisPtr, void* first);
const void* GetThisPtr() const;
const DWORD_PTR GetProcPtr() const;
BYTE m_machineCode[THUNK_CODE_LENGTH_WNDPROC];
};
// 必须使用__thiscall调用约定
struct GeneralData
{
void* Init(DWORD_PTR proc, void* thisPtr, void* first);
const void* GetThisPtr() const;
const DWORD_PTR GetProcPtr() const;
BYTE m_machineCode[THUNK_CODE_LENGTH_GENERAL];
};
#pragma pack(pop)
template<typename T>
struct ThunkData : public T
{
const void* GetCode() const { return this; }
static void* operator new(size_t size)
{
return ::VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}
static void operator delete(void* p)
{
::VirtualFree(p, 0, MEM_RELEASE);
}
};
template<typename T>
class Thunk
{
public:
Thunk() { m_thunkData = new ThunkData<T>; }
~Thunk() { delete m_thunkData; }
public:
template<typename T>
void* Get(T memberFunc, void* thisPtr, void* first = NULL)
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->Init(GetMemberFuncAddr(memberFunc), thisPtr, first);
else return NULL;
}
template<typename T>
WNDPROC GetWndProc(T memberFunc, void* thisPtr, void* first)
{
return reinterpret_cast<WNDPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
DLGPROC GetDlgProc(T memberFunc, void* thisPtr, void* first)
{
return reinterpret_cast<DLGPROC>(Get(memberFunc, thisPtr, first));
}
typedef void(* THREADPROC)(void*);
template<typename T>
THREADPROC GetThreadProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<THREADPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
LPTHREAD_START_ROUTINE GetWinThreadProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<LPTHREAD_START_ROUTINE>(Get(memberFunc, thisPtr, first));
}
template<typename T>
TIMERPROC GetTimerProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<TIMERPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
HOOKPROC GetHookProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<HOOKPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
LONG_PTR GetLongCode(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<LONG_PTR>(Get(memberFunc, thisPtr, first));
}
const void* GetCode() const
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->GetCode();
else return NULL;
}
const void* GetThisPtr() const
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->GetThisPtr();
else return NULL;
}
const DWORD_PTR GetProcPtr() const
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->GetProcPtr();
else return NULL;
}
public:
template<typename T>
static DWORD_PTR GetMemberFuncAddr(T memberFunc)
{
union
{
T from;
DWORD_PTR to;
} cast;
cast.from = memberFunc;
return cast.to;
}
private:
ThunkData<T>* m_thunkData;
};
#pragma pop_macro("new")
#pragma optimize("", on)
} // namespace qp
#5
源文件:
[/code]
/*
* Copyright (C) QPSOFT.COM All rights reserved.
*/
#include <qp/Inc.h>
#include <qp/Qp.h>
#include <qp/Thunk.h>
using namespace qp;
#pragma optimize("", off)
#if defined(_M_IX86)
/*
For __stdcall calling convention, replace 'HWND' with 'this pointer'
Stack frame before modify Stack frame after modify
: : : :
|---------------| |----------------|
| lpa | | lpa |
|---------------| |----------------|
| wpa | | wpa |
|---------------| |----------------|
| msg | | msg |
|---------------| |----------------|
| wnd | | <this pointer> |
|---------------| |----------------|
| (return addr) | <- ESP | (return addr) | <-ESP
|---------------| |----------------|
: : : :
machine code assembly instruction comment
------------------- ---------------------------- --------------
51 PUSH ECX
B8 ?? ?? ?? ?? MOV EAX, first ; EAX = first param
8B 4C 24 08 MOV ECX, DWORD PTR [ESP+08H] ; ECX = wnd
89 08 MOV DWORD PTR [EAX], ECX ; [first] = wnd
B8 ?? ?? ?? ?? MOV EAX, pthis ; EAX = this pointer
89 44 24 08 MOV DWORD PTR [ESP+08H], EAX ; overwite the 'wnd' with 'this pointer'
59 POP ECX
E9 ?? ?? ?? ?? JMP proc ; jump to target message handler
*/
void* WndProcData::Init(DWORD proc, void* thisPtr, void* first)
{
*((WORD *)&m_machineCode[ 0]) = 0xB851;
*((DWORD*)&m_machineCode[ 2]) = reinterpret_cast<DWORD>(first);
*((DWORD*)&m_machineCode[ 6]) = 0x08244C8B;
*((DWORD*)&m_machineCode[10]) = 0x00B80889;
*((DWORD*)&m_machineCode[13]) = reinterpret_cast<DWORD>(thisPtr);
*((DWORD*)&m_machineCode[17]) = 0x08244489;
*((WORD *)&m_machineCode[21]) = 0xE959;
*((DWORD*)&m_machineCode[23]) = proc - reinterpret_cast<DWORD>(this) - sizeof(WndProcData);
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(WndProcData));
return this;
}
const void* WndProcData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const DWORD*>(&m_machineCode[13]));
}
const DWORD WndProcData::GetProcPtr() const
{
return *reinterpret_cast<const DWORD*>(&m_machineCode[23]) + reinterpret_cast<DWORD>(this)
+ sizeof(WndProcData);
}
#elif defined(_M_AMD64)
/*
For x64 calling convention, rcx hold the 'HWND',copy the 'HWND' to Window object,
then insert 'this pointer' into rcx,so perfectly!!!
Stack frame before modify Stack frame after modify
: : : :
|---------------| |----------------|
| lpa | <-R9(lpa) | lpa | <-R9(lpa)
|---------------| |----------------|
| wpa | <-R8(wpa) | wpa | <-R8(wpa)
|---------------| |----------------|
| msg | <-RDX(msg) | msg | <-RDX(msg)
|---------------| |----------------|
| wnd | <-RCX(wnd) | this | <-RCX(this)
|---------------| |----------------|
| (return addr) | <-RSP | (return addr) | <-RSP
|---------------| |----------------|
: : : :
machine code assembly instruction comment
------------------- ----------------------- --------------
48 B8 ???????????????? MOV RAX, first ; RAX = first param
48 89 08 MOV QWORD PTR [RAX], RCX ; _wnd = [this] = RCX
48 B9 ???????????????? MOV RCX, thisPtr ; RCX = this pointer
48 B8 ???????????????? MOV RAX, proc
FF E0 JMP RAX
*/
void* WndProcData::Init(ULONG64 proc, void* thisPtr, void* first)
{
*((WORD *)&m_machineCode[ 0]) = 0xB848;
*((ULONG64*)&m_machineCode[ 2]) = reinterpret_cast<ULONG64>(first);
*((DWORD *)&m_machineCode[10]) = 0x00088948;
*((WORD *)&m_machineCode[13]) = 0xB948;
*((ULONG64*)&m_machineCode[15]) = reinterpret_cast<ULONG64>(thisPtr);
*((WORD *)&m_machineCode[23]) = 0xB848;
*((ULONG64*)&m_machineCode[25]) = proc;
*((WORD *)&m_machineCode[33]) = 0xE0FF;
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(WndProcData));
return this;
}
const void* WndProcData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const ULONG64*>(&m_machineCode[15]));
}
const ULONG64 WndProcData::GetProcPtr() const
{
return *reinterpret_cast<const ULONG64*>(&m_machineCode[25]);
}
#endif
#if defined(_M_IX86)
/*
For __thiscall, the default calling convention used by Microsoft VC++, The thing needed is
just set ECX with the value of 'this pointer'
machine code assembly instruction comment
-------------------- ---------------------- ---------------
B9 ?? ?? ?? ?? MOV ECX, thisPtr ; Load ecx with this pointer
E9 ?? ?? ?? ?? JMP proc ; Jump to target message handler
*/
void* GeneralData::Init(DWORD proc, void* thisPtr, void* /*first*/)
{
m_machineCode[0] = 0xB9;
m_machineCode[5] = 0xE9;
*((DWORD*)&m_machineCode[1]) = reinterpret_cast<DWORD>(thisPtr);
*((DWORD*)&m_machineCode[6]) = proc - reinterpret_cast<DWORD>(this) - sizeof(GeneralData);
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(GeneralData));
return this;
}
const void* GeneralData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const DWORD*>(&m_machineCode[1]));
}
const DWORD GeneralData::GetProcPtr() const
{
return *reinterpret_cast<const DWORD*>(&m_machineCode[6]) + reinterpret_cast<DWORD>(this)
+ sizeof(GeneralData);
}
#elif defined(_M_AMD64)
/* For x64 calling convention,insert 'this pointer' to RCX.
* Important: only for callback function with less than or equal THREE parameters,
Stack frame before modify Stack frame after modify
: ... : : ... :
|---------------| |----------------|
| | <-R8(third para) | | <-R9(third para)
|---------------| |----------------|
| | <-RDX(sencond para) | | <-R8(second para)
|---------------| |----------------|
| | <-RCX(first para) | | <-RDX(first para)
|---------------| |----------------|
| (Return Addr) | <-RSP | | <-RCX(this pointer)
|---------------| |----------------|
: ... : | (Return Addr) | <-RSP
|----------------|
: ... :
machine code assembly instruction comment
------------------- -------------------- -------
4D 8B C8 MOV R9, R8
4C 8B C2 MOV R8, RDX
48 8B D1 MOV RDX, RCX
48 B9 ???????????????? MOV RCX, thisPtr
48 B8 ???????????????? MOV RAX, proc
FFE0 JMP RAX
*/
void* GeneralData::Init(ULONG64 proc, void* thisPtr, void* /*first*/)
{
*((ULONG64*)&m_machineCode[ 0]) = 0x8B48C28B4CC88B4D;
*((DWORD *)&m_machineCode[ 8]) = 0x00B948D1;
*((ULONG64*)&m_machineCode[11]) = reinterpret_cast<ULONG64>(thisPtr);;
*((WORD *)&m_machineCode[19]) = 0xB848;
*((ULONG64*)&m_machineCode[21]) = proc;
*((WORD *)&m_machineCode[29]) = 0xE0FF;
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(GeneralData));
return this;
}
const void* GeneralData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const ULONG64*>(&m_machineCode[11]));
}
const ULONG64 GeneralData::GetProcPtr() const
{
return *reinterpret_cast<const ULONG64*>(&m_machineCode[21]);
}
#endif
#pragma optimize("", on)
[/code]
#6
有两种解决办法
第一种方法:在类中定一个类本身的静态指针变量。定义一个全局函数.如上来实现对类成员的调用.
第二种方法比较简单,把被调用的类成员函数声明为静态变量即可.
第一种方法:在类中定一个类本身的静态指针变量。定义一个全局函数.如上来实现对类成员的调用.
void* gStartVod(void* pVoid);
class Record{
friend void* gStartVod(void* pVoid);
void create_pthread_fun(void* pVoid);
void* thread(void* pVoid);
static Record *_record;
pthread_id _threadId;
}
void*
gSaveVideoData(void* pVoid)
{
Record::_record->thread(pVoid);
}
void Record::create_pthread_fun(void* pVoid)
{
pthread_create(&_threadId, NULL, gSaveVideoData2, pVoid);
}
第二种方法比较简单,把被调用的类成员函数声明为静态变量即可.
class Record{
friend void* gStartVod(void* pVoid);
void create_pthread_fun(void* pVoid);
static void* thread(void* pVoid);
pthread_id _threadId;
}
void Record::create_pthread_fun(void* pVoid)
{
pthread_create(&_threadId, NULL, thread, pVoid);
}
#7
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
class A
{
public:
void check()
{
MessageBox(NULL,"a","a",0);
}
static void BeginThread(void* lpParam)
{
((A*)lpParam)->check();
}
void run()
{
_beginthread(BeginThread,0,this);
}
};
int main()
{
A a;
a.run();
Sleep(2000);
#8
只会第二种~~~~
#1
请google之。
#2
这是我发的支持x64平台的thunk例子:
http://download.csdn.net/source/1137001
更多的thunk资源下载: http://search.download.csdn.net/search/thunk
更多的thunk资源下载: http://search.download.csdn.net/search/thunk
#3
起类方法线程, static, _beginthread最好加上ex.
#4
这里的文章及源码都很精彩:
http://www.vckbase.com/document/finddoc.asp?keyword=thunk
thunk在ATL中得到广泛应用。
这是我写过的thunk封装。
thunk在ATL中得到广泛应用。
这是我写过的thunk封装。
/*
* Copyright (C) QPSOFT.COM All rights reserved.
*/
#pragma once
namespace qp
{
#if defined(_M_IX86)
#define THUNK_CODE_LENGTH_WNDPROC 27
#define THUNK_CODE_LENGTH_GENERAL 10
#elif defined(_M_AMD64)
#define THUNK_CODE_LENGTH_WNDPROC 35
#define THUNK_CODE_LENGTH_GENERAL 31
#endif
#pragma optimize("", off)
#pragma push_macro("new")
#undef new
#pragma pack(push,1)
// 必须使用__stdcall调用约定
struct WndProcData
{
void* Init(DWORD_PTR proc, void* thisPtr, void* first);
const void* GetThisPtr() const;
const DWORD_PTR GetProcPtr() const;
BYTE m_machineCode[THUNK_CODE_LENGTH_WNDPROC];
};
// 必须使用__thiscall调用约定
struct GeneralData
{
void* Init(DWORD_PTR proc, void* thisPtr, void* first);
const void* GetThisPtr() const;
const DWORD_PTR GetProcPtr() const;
BYTE m_machineCode[THUNK_CODE_LENGTH_GENERAL];
};
#pragma pack(pop)
template<typename T>
struct ThunkData : public T
{
const void* GetCode() const { return this; }
static void* operator new(size_t size)
{
return ::VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}
static void operator delete(void* p)
{
::VirtualFree(p, 0, MEM_RELEASE);
}
};
template<typename T>
class Thunk
{
public:
Thunk() { m_thunkData = new ThunkData<T>; }
~Thunk() { delete m_thunkData; }
public:
template<typename T>
void* Get(T memberFunc, void* thisPtr, void* first = NULL)
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->Init(GetMemberFuncAddr(memberFunc), thisPtr, first);
else return NULL;
}
template<typename T>
WNDPROC GetWndProc(T memberFunc, void* thisPtr, void* first)
{
return reinterpret_cast<WNDPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
DLGPROC GetDlgProc(T memberFunc, void* thisPtr, void* first)
{
return reinterpret_cast<DLGPROC>(Get(memberFunc, thisPtr, first));
}
typedef void(* THREADPROC)(void*);
template<typename T>
THREADPROC GetThreadProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<THREADPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
LPTHREAD_START_ROUTINE GetWinThreadProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<LPTHREAD_START_ROUTINE>(Get(memberFunc, thisPtr, first));
}
template<typename T>
TIMERPROC GetTimerProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<TIMERPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
HOOKPROC GetHookProc(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<HOOKPROC>(Get(memberFunc, thisPtr, first));
}
template<typename T>
LONG_PTR GetLongCode(T memberFunc, void* thisPtr, void* first = NULL)
{
return reinterpret_cast<LONG_PTR>(Get(memberFunc, thisPtr, first));
}
const void* GetCode() const
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->GetCode();
else return NULL;
}
const void* GetThisPtr() const
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->GetThisPtr();
else return NULL;
}
const DWORD_PTR GetProcPtr() const
{
qpASSERT(m_thunkData != NULL);
if (m_thunkData != NULL) return m_thunkData->GetProcPtr();
else return NULL;
}
public:
template<typename T>
static DWORD_PTR GetMemberFuncAddr(T memberFunc)
{
union
{
T from;
DWORD_PTR to;
} cast;
cast.from = memberFunc;
return cast.to;
}
private:
ThunkData<T>* m_thunkData;
};
#pragma pop_macro("new")
#pragma optimize("", on)
} // namespace qp
#5
源文件:
[/code]
/*
* Copyright (C) QPSOFT.COM All rights reserved.
*/
#include <qp/Inc.h>
#include <qp/Qp.h>
#include <qp/Thunk.h>
using namespace qp;
#pragma optimize("", off)
#if defined(_M_IX86)
/*
For __stdcall calling convention, replace 'HWND' with 'this pointer'
Stack frame before modify Stack frame after modify
: : : :
|---------------| |----------------|
| lpa | | lpa |
|---------------| |----------------|
| wpa | | wpa |
|---------------| |----------------|
| msg | | msg |
|---------------| |----------------|
| wnd | | <this pointer> |
|---------------| |----------------|
| (return addr) | <- ESP | (return addr) | <-ESP
|---------------| |----------------|
: : : :
machine code assembly instruction comment
------------------- ---------------------------- --------------
51 PUSH ECX
B8 ?? ?? ?? ?? MOV EAX, first ; EAX = first param
8B 4C 24 08 MOV ECX, DWORD PTR [ESP+08H] ; ECX = wnd
89 08 MOV DWORD PTR [EAX], ECX ; [first] = wnd
B8 ?? ?? ?? ?? MOV EAX, pthis ; EAX = this pointer
89 44 24 08 MOV DWORD PTR [ESP+08H], EAX ; overwite the 'wnd' with 'this pointer'
59 POP ECX
E9 ?? ?? ?? ?? JMP proc ; jump to target message handler
*/
void* WndProcData::Init(DWORD proc, void* thisPtr, void* first)
{
*((WORD *)&m_machineCode[ 0]) = 0xB851;
*((DWORD*)&m_machineCode[ 2]) = reinterpret_cast<DWORD>(first);
*((DWORD*)&m_machineCode[ 6]) = 0x08244C8B;
*((DWORD*)&m_machineCode[10]) = 0x00B80889;
*((DWORD*)&m_machineCode[13]) = reinterpret_cast<DWORD>(thisPtr);
*((DWORD*)&m_machineCode[17]) = 0x08244489;
*((WORD *)&m_machineCode[21]) = 0xE959;
*((DWORD*)&m_machineCode[23]) = proc - reinterpret_cast<DWORD>(this) - sizeof(WndProcData);
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(WndProcData));
return this;
}
const void* WndProcData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const DWORD*>(&m_machineCode[13]));
}
const DWORD WndProcData::GetProcPtr() const
{
return *reinterpret_cast<const DWORD*>(&m_machineCode[23]) + reinterpret_cast<DWORD>(this)
+ sizeof(WndProcData);
}
#elif defined(_M_AMD64)
/*
For x64 calling convention, rcx hold the 'HWND',copy the 'HWND' to Window object,
then insert 'this pointer' into rcx,so perfectly!!!
Stack frame before modify Stack frame after modify
: : : :
|---------------| |----------------|
| lpa | <-R9(lpa) | lpa | <-R9(lpa)
|---------------| |----------------|
| wpa | <-R8(wpa) | wpa | <-R8(wpa)
|---------------| |----------------|
| msg | <-RDX(msg) | msg | <-RDX(msg)
|---------------| |----------------|
| wnd | <-RCX(wnd) | this | <-RCX(this)
|---------------| |----------------|
| (return addr) | <-RSP | (return addr) | <-RSP
|---------------| |----------------|
: : : :
machine code assembly instruction comment
------------------- ----------------------- --------------
48 B8 ???????????????? MOV RAX, first ; RAX = first param
48 89 08 MOV QWORD PTR [RAX], RCX ; _wnd = [this] = RCX
48 B9 ???????????????? MOV RCX, thisPtr ; RCX = this pointer
48 B8 ???????????????? MOV RAX, proc
FF E0 JMP RAX
*/
void* WndProcData::Init(ULONG64 proc, void* thisPtr, void* first)
{
*((WORD *)&m_machineCode[ 0]) = 0xB848;
*((ULONG64*)&m_machineCode[ 2]) = reinterpret_cast<ULONG64>(first);
*((DWORD *)&m_machineCode[10]) = 0x00088948;
*((WORD *)&m_machineCode[13]) = 0xB948;
*((ULONG64*)&m_machineCode[15]) = reinterpret_cast<ULONG64>(thisPtr);
*((WORD *)&m_machineCode[23]) = 0xB848;
*((ULONG64*)&m_machineCode[25]) = proc;
*((WORD *)&m_machineCode[33]) = 0xE0FF;
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(WndProcData));
return this;
}
const void* WndProcData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const ULONG64*>(&m_machineCode[15]));
}
const ULONG64 WndProcData::GetProcPtr() const
{
return *reinterpret_cast<const ULONG64*>(&m_machineCode[25]);
}
#endif
#if defined(_M_IX86)
/*
For __thiscall, the default calling convention used by Microsoft VC++, The thing needed is
just set ECX with the value of 'this pointer'
machine code assembly instruction comment
-------------------- ---------------------- ---------------
B9 ?? ?? ?? ?? MOV ECX, thisPtr ; Load ecx with this pointer
E9 ?? ?? ?? ?? JMP proc ; Jump to target message handler
*/
void* GeneralData::Init(DWORD proc, void* thisPtr, void* /*first*/)
{
m_machineCode[0] = 0xB9;
m_machineCode[5] = 0xE9;
*((DWORD*)&m_machineCode[1]) = reinterpret_cast<DWORD>(thisPtr);
*((DWORD*)&m_machineCode[6]) = proc - reinterpret_cast<DWORD>(this) - sizeof(GeneralData);
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(GeneralData));
return this;
}
const void* GeneralData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const DWORD*>(&m_machineCode[1]));
}
const DWORD GeneralData::GetProcPtr() const
{
return *reinterpret_cast<const DWORD*>(&m_machineCode[6]) + reinterpret_cast<DWORD>(this)
+ sizeof(GeneralData);
}
#elif defined(_M_AMD64)
/* For x64 calling convention,insert 'this pointer' to RCX.
* Important: only for callback function with less than or equal THREE parameters,
Stack frame before modify Stack frame after modify
: ... : : ... :
|---------------| |----------------|
| | <-R8(third para) | | <-R9(third para)
|---------------| |----------------|
| | <-RDX(sencond para) | | <-R8(second para)
|---------------| |----------------|
| | <-RCX(first para) | | <-RDX(first para)
|---------------| |----------------|
| (Return Addr) | <-RSP | | <-RCX(this pointer)
|---------------| |----------------|
: ... : | (Return Addr) | <-RSP
|----------------|
: ... :
machine code assembly instruction comment
------------------- -------------------- -------
4D 8B C8 MOV R9, R8
4C 8B C2 MOV R8, RDX
48 8B D1 MOV RDX, RCX
48 B9 ???????????????? MOV RCX, thisPtr
48 B8 ???????????????? MOV RAX, proc
FFE0 JMP RAX
*/
void* GeneralData::Init(ULONG64 proc, void* thisPtr, void* /*first*/)
{
*((ULONG64*)&m_machineCode[ 0]) = 0x8B48C28B4CC88B4D;
*((DWORD *)&m_machineCode[ 8]) = 0x00B948D1;
*((ULONG64*)&m_machineCode[11]) = reinterpret_cast<ULONG64>(thisPtr);;
*((WORD *)&m_machineCode[19]) = 0xB848;
*((ULONG64*)&m_machineCode[21]) = proc;
*((WORD *)&m_machineCode[29]) = 0xE0FF;
::FlushInstructionCache(::GetCurrentProcess(), this, sizeof(GeneralData));
return this;
}
const void* GeneralData::GetThisPtr() const
{
return reinterpret_cast<const void*>(*reinterpret_cast<const ULONG64*>(&m_machineCode[11]));
}
const ULONG64 GeneralData::GetProcPtr() const
{
return *reinterpret_cast<const ULONG64*>(&m_machineCode[21]);
}
#endif
#pragma optimize("", on)
[/code]
#6
有两种解决办法
第一种方法:在类中定一个类本身的静态指针变量。定义一个全局函数.如上来实现对类成员的调用.
第二种方法比较简单,把被调用的类成员函数声明为静态变量即可.
第一种方法:在类中定一个类本身的静态指针变量。定义一个全局函数.如上来实现对类成员的调用.
void* gStartVod(void* pVoid);
class Record{
friend void* gStartVod(void* pVoid);
void create_pthread_fun(void* pVoid);
void* thread(void* pVoid);
static Record *_record;
pthread_id _threadId;
}
void*
gSaveVideoData(void* pVoid)
{
Record::_record->thread(pVoid);
}
void Record::create_pthread_fun(void* pVoid)
{
pthread_create(&_threadId, NULL, gSaveVideoData2, pVoid);
}
第二种方法比较简单,把被调用的类成员函数声明为静态变量即可.
class Record{
friend void* gStartVod(void* pVoid);
void create_pthread_fun(void* pVoid);
static void* thread(void* pVoid);
pthread_id _threadId;
}
void Record::create_pthread_fun(void* pVoid)
{
pthread_create(&_threadId, NULL, thread, pVoid);
}
#7
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
class A
{
public:
void check()
{
MessageBox(NULL,"a","a",0);
}
static void BeginThread(void* lpParam)
{
((A*)lpParam)->check();
}
void run()
{
_beginthread(BeginThread,0,this);
}
};
int main()
{
A a;
a.run();
Sleep(2000);
#8
只会第二种~~~~