>Basic Question:
>       How do you use a C++ method as a callback function?

I've seen a few of these in the last few days.

A simple example lifted from "Noah J. Ternullo" <[EMAIL PROTECTED]>:

Class A {
private:
        FormPtr myFormPtr; //pointer to a valid form
public:
          //  method trying to setup an event handler for the form
        void setup();
         //  method which is the event handler for the form
        Boolean handleEvent(EventPtr eventPtr)  
}

void A::setup() {
     FrmSetEventHandler ( myFormPtr,  handleEvent ); // error!!
}

This can't work.

The reason it can't work is that every (non-static) member function
has an "invisible" parameter, which is the object whose member function
is being called. You refer to this parameter by the special name "this".

So, when you write:
        Boolean handleEvent(EventPtr eventPtr)
the compiler generates:
        Boolean handleEvent ( A *this, EventPtr eventPtr)

And if you write:
        FrmSetEventHandler ( myFormPtr,  handleEvent );
then you get (as Mr. Turnullo found out):

Error   : cannot convert
'unsigned char (A::*)(const void *const , EventType *)' to
'unsigned char (*const )(EventType *)'

The solution is simple to state, rather harder to implement.
Make the member function static. If it's static, then you don't
have an associated object, and there is no 'this' parameter.

But, I can hear you saying "The whole point of having an object
is to be able to access the data associated with that object,
and you've just thrown that away!". Yes, I have. :-(

So, you need some way to recover the object. It can't be
passed as a parameter to the callback (there's no available
parameter). The simple (and ugly way) is to use a global variable.
This works best if you only have one instance of your class active
at a time. You can add a line to the class declaration like this:

static A* theCurrentForm;

set it in A::Setup, and access it in handleEvent. In fact, you can then
declare handleEvent non-static, and declare a forwarding function called
something like HandleEventShim, which recovers the object from the global
and forwards the call to handleEvent.

A more elegant solution would involve packaging the object and the function
pointer together in a package that could automatically act as such a shim. The
standard C++ library template mem_fun is designed to do things like that. However,
all my Palm development stuff is at home today, so I can't tell you if that will
work on the Palm. I will follow this up tonight.....
-- 
-- Marshall

"The era of big government is over."
           Bill Clinton, State of the Union Address, January 23, 1996
Marshall Clow     Adobe Systems   <mailto:[EMAIL PROTECTED]>

-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palm.com/devzone/mailinglists.html

Reply via email to