|
Winapi Callback C++ member function. |
Goalie Ca
Member #2,579
July 2002
|
Here's the problem: Create a self-contained class for any one of many types of winapi functions. Catch: the callback is a member function. The issue is the stack produced by the type of call. The solution is probably achieved through binding/similar mechanism. Traditional std::mem_fun doesn't work. boost::mem_fn can actually handle the callback and its quirks. The problem is actually passing it if i'm using boost. Currently I have a singleton class.. the callback is static. This is fine for this class because it IS a singleton by nature. But soon i will need to make a non-singleton class with the same problem. I've google this so far and haven't found much. I've found a thunking technique which is basically an assembly hack.. mfc uses that. Maybe i should pick up myself that book from the apple commercial "C++ gui programming". I can see why you'd need it ------------- |
orz
Member #565
August 2000
|
Quote:
The problem is actually passing it if i'm using boost.
I haven't use boost, or (except every once in a while) the win32 API. Probably I'm misunderstanding something here. But here's my reaction to your question: |
ImLeftFooted
Member #3,935
October 2003
|
map<DWORD, void*> pointerLookup; Pretty simple, when you think about it. |
Goalie Ca
Member #2,579
July 2002
|
Thanks for your help guys but I'm pretty convinced now that there's no clean way to solve it. Reading the implementations of bind, bind1st, mem_fn, mem_fun etc.. i realize what they do. They create structs that wrap the c++ call. This normally works fine for c++ libraries but isn't able to get around the limitation of c-libraries. For instance.. say i could even create a static function, and all i wanted to do was bind some argument such as "this" to it (so i could do this->something(args)). This returns a struct with overloaded () operators. Naturally this struct also has the same problem as my member callback. Apparently this is called the c++ forwarding problem. Orz: Dustin: But it just got me thinking.. Windows normally passes HWND or some handle usually (after all c has to deal with it). I could use a map based on the handle! With a semaphore lock it might just work.. I'll post results when i get around to it tomorrow. Cookie if it works. ------------- |
Kitty Cat
Member #2,815
October 2002
|
Quote: I didn't know DWORD_PTR = DWORD. Isn't dword = double word. Yup. And WORD on MSVC is 16-bit, so DWORD is double that.. 32-bit. Not sure how DWORD_PTR is handled on 64-bit targets, though. However, for C callbacks with non-static C++ methods, the funciton needs to take a user-pointer to pass along to the callback you give it, then give it a static callback and pass 'this' as the user-pointer. Then in the static callback, cast the user-pointer to the class type, and call the non-static member. class SomeClass { real_callback() { ... } some_static_callback(void *ptr) { static_cast<SomeClass*>(ptr)->real_callback(); } foo() { SetSomeWin32Callback(some_static_callback, this); } Though if you can't pass 'this' for a user pointer, then you're out of luck. -- |
orz
Member #565
August 2000
|
Quote: Thanks for your help guys but I'm pretty convinced now that there's no clean way to solve it.
C callbacks != perfectly clean Quote: I didn't know DWORD_PTR = DWORD. Isn't dword = double word. DWORD_PTR would then not have different sizes on 32 and 64-bit platforms? Hm... you're probably right. All I can see here is what DWORD and DWORD_PTR is on my compiler. Perhaps on a 64 bit compiler a DWORD would still be 32 bit while a DWORD_PTR would grow to 64 bits. So, forget about my second question. My first question still stands though. I still don't really understand what the issue is. C callbacks to template functions work fine for me, although not to functors (add an extra wrapper if mem_fn is a functor?). |
Goalie Ca
Member #2,579
July 2002
|
Well the issue here is that say you have this (although true of any C++ class wrapping any winapi object).
The callback is a member function of a class. A standard c-callback in WINAPI uses __stdcall (that's what CALLBACK is defined to be). Problems.. well in C++ there is a hidden "this" parameter added to every member function call. And in C++ if you use polymorphism or anything fancier it's even more broken. So my first misguided attempt was to try and wrap that call with mem_fn, mem_fun, etc.. But those create a struct with an overloaded () operator. This does not fix anything. What i will try is to make a static function. Inside it I will have a map<HANDLE, CWindow*>. That map will be static. I will then call the appropriate function then. ------------- |
Tobias Dammers
Member #2,604
August 2002
|
If the HANDLE is a HWND, then you can store a pointer to the CWindow in the window's extra memory, and access it through GetWindowLong() / SetWindowLong(). This way, you don't have the map overhead. --- |
nonnus29
Member #2,606
August 2002
|
Do you know there are a couple of extensive documents on the intarwebs that go thru this procedure (wrapping win32 api)? If you're just inventing a wheel that's great, I think it's a horrible waste of time though..... |
gillius
Member #119
April 2000
|
C# is the ultimate wrapper around the Win32 API . Sorry, just playing and trolling around. Gillius |
Goalie Ca
Member #2,579
July 2002
|
Tobias FTW!!! static LRESULT CALLBACK staticCallback (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { CWindow* instance = reinterpret_cast<CWindow*>(GetWindowLongPtr(hwnd, DWLP_USER)); return instance->WindowProcedure(hwnd, message, wParam, lParam); } Cookies to tobias Gillius: I've used C# winforms lots. I find it quite retarded how there's no built-in printing for text boxes, hardware accelerated blitting (gdi+ is all software based!) and how rich text box is absolutely useless because of the font attribute rules. edit: just realized that while most buttons etc. are handle based there are also timers, waveIn, waveOut, ..etc I will have to look into that. I guess i just got exited there was a simple solution. Most of the crud on the net involved "thunk" and other crude hacks (not sure how portable that is.. its essentially an assembly hack). This technique though seems to have promise. Otherwise i guess i could still use a map for other structs. ------------- |
|