Feedback wanted from anyone using attach()/rise()/etc with pointer to member functions?

04 Jul 2010 . Edited: 04 Jul 2010

Please ignore if the title didn't make sense; this is probably only interesting to a minority of people!

I've been doing some experiments tonight around pointers to member functions (among other things). The main problem is C++ really doesn't handle them at all well, and to get the functionality I wanted to allow people to register member functions as handlers in the current library, I really had to pull of some horrible tricks (even had to bring out memcpy in the trampoline :(.

However, I think i've finally hit on a better way based on reframing the problem slightly, and just want to give people a chance to shout if for some reason this new approach wouldn't work for them. I haven't worked through everything so there may be some hidden gotchas, but it is much simpler and gives basically the same functionality so I am very likely to make this change assuming there are no blockers.

Here is the explanation:

Currently, any class that accepts registration of static functions and member functions basically has something like the following:

void attach(void (*function)(void));

template <class T>
void attach(T *object, void (T::*member)(void));

Whilst the interface is ok(ish), the implementation for this has to jump through hoops. It basically comes from the problem that pointers to member functions are not guaranteed to be alike. It also means new code generated for every type of member function attached (it is a template), which carries through to classes that expose it further up the chain.

Ok, so what I propose is that the basic static attach can also provide a void* pointer to some data, that is provided back on callback. And as soon as it does that, everything gets much easier! (hindsight is a wonderful thing!). So now for member functions, the data pointer is just the this pointer, and the member function is wrapped in a static templated trampoline function i've called "member", to call the chosen member of the object:

void attach(void (*function)(void*), void *data);

template<class T, void (T::*member)(void)>
void member(void *object);                 

So e.g. to setup a callback to a member function of an object, it's now look like:

class Foo {
    Foo() {
        x.attach(member<Foo, &Foo::bar>, this);
    }
    void bar();          // desired callback function
    AttachableObject x;  // object with event
};

I think this is actually even a little simpler to use as it keeps the attach functions simpler too, and much better for implementation and reuse.

Please shout if you followed it this far and have an opinion either way!

Simon

05 Jul 2010

Have you looked at using references instead of pointers?

Also, is it a good idea to allow member functions as handlers? What if the instance of the class containing the member function used as a handler is unintentionally deleted?

 

13 Jul 2010

Struggling with this one. I recently created a load of code that handles a MAX7456 on-screen display chip. I did it "the old fashioned way" with a pile of C functions. All works fine.

So then I decided would be nice to publish it so decided to convert "a pile of C functions" into a nice easy to use class. All went well up until I reached this point.

The MAX7456 has a vertical sync pulse output. Now I know the chip can be configured to update the display area during the vertical blanking period, however, my app does other things with the sync pulse, so I wanted to handle it within the class also. This is where I come unstuck.

I have a private InterruptIn and I want to connect it's .fall() to a member function. This was easy in straight C but in this class C++ way of doing things I just can't fathom how to attach the .fall() callback to a member function within the class. The compiler just keeps barking "Nonstandard form for taking the address of a member function (E504-D)"

Any tips please?

18 Oct 2011

I know this thread is really old, but I am VERY interested in the outcome.

I've been wrestling with something for a few days now: I'm making a class with a method that works very similar to attach(). I even want to overload it for cases of static and member functions. Getting the static case to work is simple enough, but I can't figure out how you did the member function case. I would like the user to be able to use a simple interface without totally wrecking the class.

so, I think I've got it down to this: somehow you are storing the class object pointer and member function pointer with the attach(), and allowing you class to call those pointers when needed. Is there any hope of learning how you did this?

I'm in favor of the new way, seems like a better implementation and it looks a bit less arcane than the first one.