Use thunk to change C ++ member functions to callback Functions

Source: Internet
Author: User

For Windows APIs, callback functions are often required. In C ++ development, object-oriented functions are recommended. If a member function of the C ++ class can be called as a callback function, it would be great! However, all c ++ member functions implicitly use this pointer to point to the current object. It is really not easy to implement callback.

I have been familiar with thunk Technology about a year ago, and even have seen examples of using thunk to convert member functions into callback functions. However, I have never really understood what C ++ looks like after compilation. It's easy to get a tip, and I can't understand it. I don't dare to use their programs directly. After all, it's hard to handle errors. Some time ago, I think of thunk technology occasionally. Being unskillful, it is very likely that thunk will affect my programmer's career. So I decided to close my mind (no way, poor qualifications) and finally figured it out. That feeling is like a person who is honest and LIFO suddenly sees it, or changes to a metaphor that is close to himself: just as excited to see a beautiful girl for thousands of years.
I couldn't help but imitate the sighs of the man in the novel after he suddenly realized the greatest truths: It turns out like this!

Below I will share my gains, which are basically written to beginners. The hero must stop, and the younger brother is thin!

I have studied the code after C ++ assembly. Before calling C ++ member functions, the ECX register is used to save the object pointer, fortunately, the call conventions of C ++ member functions _ the parameter pressure stack sequence of thiscall and the maintenance of stack balance are the same as the call conventions of callback functions _ stdcall, therefore, you only need to construct an assembly to save the object pointer in the ECX register and then run JMP to the execution address of the member function. Write a C ++ structure to piece together the two Assembly codes:
# Pragma pack (push, 1)
Struct memfuntostdcallthunk
{
Byte m_mov;
DWORD m_this;
Byte m_jmp;
DWORD m_relproc;
Bool Init (dword_ptr proc, void * pthis)
{
M_mov = 0xb9;
M_this = ptrtoulong (pthis );
M_jmp = 0xe9;
M_relproc = DWORD (int_ptr) proc-(int_ptr) This + sizeof (memfuntostdcallthunk )));
: Flushinstructioncache (: getcurrentprocess (), this, sizeof (memfuntostdcallthunk ));
Return true;
}
Void * getcodeaddress ()
{
Return this;
}
};
# Pragma pack (POP)
This structure is equivalent to two Assembly statements:
MoV ECx, pthis
JMP [offset address]
Usage:
Class ctestclass
{
PRIVATE:
Int m_nbase;
Memfuntostdcallthunk m_thunk;
Void memfun (int m, int N)
{
Int nsun = m_nbase + M + N;
Cstring STR;
Str. Format (_ T ("% d"), nsun );
Atlmessagebox (null, _ u_stringorid (STR ));
}
Public:
Ctestclass ()
{
M_nbase = 10;
}
Void test ()
{
// Unioncasttype: Convert the function pointer to dword_ptr using the Union.
M_thunk.init (unioncasttype <dword_ptr> (& ctestclass: memfun), this );
Stdcallfun fun = (stdcallfun) m_thunk.getcodeaddress ();
Atlassert (fun! = NULL );
Fun (1, 3 );
}
};
The init method of memfuntostdcallthunk accepts the member function pointer and object pointer and constructs two Assembly codes. When fun () is called, the parameters 3 and 1 are first pushed into the stack, then jump to m_thunk, that is, the constructed two Assembly codes, save the object pointer to the ECX register, and then jump to the specified member function for execution. Everything is OK.
The code for the unioncasttype method is as follows:
Template <typename tdst, typename tsrc>
Tdst unioncasttype (tsrc SRC)
{
Union
{
Tdst udst;
Tsrc usrc;
} Umedia;
Umedia. usrc = SRC;
Return umedia. udst;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.