Class methods as callback functions

This the the forum for potential authors to submit article ideas.

Moderator: 2ffat

Class methods as callback functions

Postby rlebeau » Tue Feb 26, 2008 5:07 pm

A classic issue that comes up again and again - how to use class methods as callbacks for APIs that require plain functions instead, especially for APIs that do not provide the option of passing user-defined values as part of the callbacks. Most people want their callbacks to access members of objects that are using the APIs. For the feint of heart, using global pointers to the desired objects is usually the only way to go. Although it works, it has its share of limitations.

I recently came across this problem myself for the up-teenth time in one of my own projects. So for several days now I have been researching and tinkering with an alternative approach that even the VCL itself uses internally - proxy functions.

Specifically, the VCL has a MakeObjectInstance() function (and accompanied FreeObjectInstance() function) which allows a class method of a particular signature (TWndMethod) to be used as a Win32 API window procedure callback. In other words, any class method with the following signature:

Code: Select all
void __fastcall (__closure*)(TMethod&)


Can be converted to a WNDPROC via MakeObjectInstance():

Code: Select all
LRESULT WINAPI (*)(HWND, UINT, WPARAM, LPARAM)


And then passed to CreateWindow/Ex() or SetWindowLong(). Every VCL control that is derived from TWinControl, or uses AllocateHWnd() internally (such as TTimer), use MakeObjectInstance() to receive their window messages from the OS this way.

What I have been working on this past week is a new set of proxy code that takes MakeObjectInstance() to a whole new level. Specifically, I've taken Borland's basic proxy stub code and abstracted it out so it can be used with any kind of class method of any signature. The main proxying is controlled by a user-defined function for each proxy that is generated.

So far, I have made several passthrough proxies that support the most common calling conventions - cdecl, stdcall, and Borland's fastcall. These require the source and target signatures to match other than the use of __closure, for example:

Code: Select all
char* __cdecl (__closure *)(char*, char*, ...)

to
Code: Select all
char* __cdecl (*)(char*, char*, ...)


Code: Select all
bool __stdcall (__closure *)(double)

to
Code: Select all
bool __stdcall (*)(double)


Code: Select all
void __fastcall (__closure *)(int)

to
Code: Select all
void __fastcall (*)(int)


Etc. I have also written a few conversion proxies as well (cdecl to stdcall, cdecl to fastcall, stdcall to fastcall), for more advanced uses where the source and target parameters and/or calling conventions differ, for example:

Code: Select all
void __fastcall (__closure *)(char*, char*, bool&)

to
Code: Select all
bool __cdecl (*)(char*, char*)


The best part is that because the underlying code is generic, users can write their own custom proxies to suit their particular needs. Of course, they need to have an understanding of Assembly and how it pertains to Borland's compilers, or at least an understanding of how various code constructs are outputted into Assembly (a few of my own proxies can be expressed in either pure Assembly or normal C++ coding, based on a #define).
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1487
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Class methods as callback functions

Postby rlebeau » Wed Mar 05, 2008 2:54 am

gambit47 wrote:What I have been working on this past week is a new set of proxy code that takes MakeObjectInstance() to a whole new level.


I have started writing this article tonight, and it is already clear to me that it will become a 3-part series. I will introduce the classic scenerios and pitfalls in Part 1, then explain how MakeObjectInstance() works in Part 2, and finally in Part 3 I will show how I implement a new architecture to replace MakeObjectInstance() with something far more flexible.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1487
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Postby 2ffat » Wed Mar 05, 2008 6:39 am

I would be very interested in an article or articles on this. On a side note, there are several things like this that authors assume readers understand but I see people asking again and again in forums. Maybe a series a "back-to-basics" articles.
James P. Cottingham

Look at me still talking
when there is science to do.
User avatar
2ffat
Forum Mod
Forum Mod
 
Posts: 431
Joined: Wed Jun 23, 2004 7:07 am
Location: South Hill, VA

Postby Damon » Thu Mar 06, 2008 9:04 am

I like the idea of proxies. I think this will be a very popular and useful topic, and I personally look forward to reading the articles.

I also like the idea of a back-to-basics series. What basics do you think are most pertinent to cover?

Cheers,
Damon
Damon Chandler
Editor-in-Chief
C++Builder Developer's Journal
http://bcbjournal.com
User avatar
Damon
BCBJ Editor and Admin
BCBJ Editor and Admin
 
Posts: 285
Joined: Wed May 26, 2004 11:25 pm
Location: Stillwater, OK, USA


Return to Manuscript Proposals

Who is online

Users browsing this forum: No registered users and 3 guests