c++中多线程方法可以调用类里的方法吗?

时间:2022-03-22 18:29:38
例如有一类a 如下:
 

class a{
  public:
     void check(void * param)
     {
         MessageBox(NULL,"a","a",0);
     }

     void run()
     {
         _begindthread(check,NULL,NULL);
      }
}

为什么我这样调用不了?请问一下有别的好的解决方案吗?能够提供示例代码最好。先谢谢了。

8 个解决方案

#1


本帖最后由 Loaden 于 2011-05-27 20:37:41 编辑
thunk
请google之。

#2


这是我发的支持x64平台的thunk例子: http://download.csdn.net/source/1137001
更多的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封装。
/*
 * 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


源文件:



/*
 * 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


只会第二种~~~~
引用 6 楼 yfkiss 的回复:
有两种解决办法

第一种方法:在类中定一个类本身的静态指针变量。定义一个全局函数.如上来实现对类成员的调用.
C/C++ code

void*  gStartVod(void* pVoid);
class Record{
 friend void*  gStartVod(void* pVoid);

 void create_pthread_fun(void* pVoid);
 voi……

#1


本帖最后由 Loaden 于 2011-05-27 20:37:41 编辑
thunk
请google之。

#2


这是我发的支持x64平台的thunk例子: http://download.csdn.net/source/1137001
更多的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封装。
/*
 * 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


源文件:



/*
 * 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


只会第二种~~~~
引用 6 楼 yfkiss 的回复:
有两种解决办法

第一种方法:在类中定一个类本身的静态指针变量。定义一个全局函数.如上来实现对类成员的调用.
C/C++ code

void*  gStartVod(void* pVoid);
class Record{
 friend void*  gStartVod(void* pVoid);

 void create_pthread_fun(void* pVoid);
 voi……