Thread: Setting up classes to handle callback functions

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    204

    Setting up classes to handle callback functions

    Hi Guys,
    so hopefully this question is going to cause less controversy around the forum than yesterday's (those of you who were there know what Im talking about )
    I have been reading about callback functions - something I came across a long time ago when I copy pasted some code that used for, thoguht it was pretty magic, but didnt try and understand it. Now I am...
    So here's a small program:
    Code:
    #include <iostream>
    #include <windows.h>
    using namespace std;
    
    BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int iCmdShow)
    {
    	EnumWindows(EnumWindowsProc, NULL);
    
    	return 0;
    }
    
    BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
    {
    
    cout << "In callback method" << endl ;
    
    
    	return TRUE;
    }
    What Im struggling with is how to put this in a class - I mean the call back function.
    If I create a class and I want to use call EnumWindows, this passes itself EnumWindowsProc. But I cant work out how to declare it within a class, so it is part of an object.
    Thanks

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Using ISO C callbacks with C++ class methods that need access to instance specific data requires an intermediary function to wrap the `this' pointer.

    It may look like a million different things, but there is no other portable and reasonable option.

    I prefer a parametric polymorphisms based approach, but virtual polymorphisms and simple "hard coding" certainly options.

    [Edit]
    And yes, the need for the intermediary function to deal with the `this' pointer may mean that some functions requiring such a callback can't be used with classes without jumping through bogus hoops (global state) or horrible hacks (generated thunks).
    [/Edit]

    [Edit]
    Adapted "in place" from your example; beware of incomplete or malformed expressions.
    [/Edit]

    Soma

    Code:
    // ...
    
    // core callback: wrapps ugly casting using whatever method you like
    
    template
    <
        typename FTarget
    >
    BOOL CALLBACK ClassEnumWindowsProc(HWND hwnd, LPARAM lParam)
    {
        FTarget * sThis(reinterpret_cast<lParam>);
        return(OVERLOADEDEnumWindowsProc(hwnd, *sThis));
    }
    
    // ...
    
    class MyClass;
    
    // ...
    
    // type (class) specific overload so we can use facilities of a clas
    
    BOOL OVERLOADEDEnumWindowsProc(HWND hwnd, MyClass & fWhatever)
    {
        // ...
        // use MyClass interface from fWhatever
        // ...
    }
    
    // ...
    
    // and an interface for simplicity
    
    template
    <
        typename FTarget
    >
    BOOL MyEnumWindows(FTarget & fThis)
    {
    EnumWindows(&ClassEnumWindowsProc<FTarget>, &fThis);
    }
    
    // ...
    // or without the wrapper
    EnumWindows(&ClassEnumWindowsProc<MyClass>, ((MyClass *)(&MyClassInstance))); // verbose with intent
    // ...
    Last edited by phantomotap; 09-16-2012 at 04:00 AM.

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Any callback which isn't broken will give a way to pass a user-defined parameter into the callback. Use this parameter to pass the "this" pointer of the object you are calling back into, and use a static method to provide the callback itself. The static method will cast the user defined parameter back into an object pointer and invoke the callback (non-static) method. Any callback parameters which are needed should be held in instance variables.

    If a callback does NOT provide a way to pass a user-defined parameter, then you are looking at code written by a buffoon (the creator of the callback, not you).

    In the case of EnumWindows(), the parameter is provided, so you can do the right thing.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    If you want to learn about this in more depth it may be worth looking through the Function Pointer Tutorials.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with setting text into LTEXT using Window Handle
    By jasperleeabc in forum Windows Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Callback Functions
    By valaris in forum C Programming
    Replies: 11
    Last Post: 07-31-2008, 09:20 PM
  3. CallBack Functions
    By manofsteel972 in forum Windows Programming
    Replies: 4
    Last Post: 11-04-2004, 04:04 PM
  4. Callback functions from dll
    By Calthun in forum Windows Programming
    Replies: 2
    Last Post: 07-09-2004, 04:13 PM
  5. Callback functions
    By linuxdude in forum C Programming
    Replies: 2
    Last Post: 01-03-2004, 06:23 PM