Methods always contain a hidden this
parameter to provide access to the object being invoked. To call a class from an interrupt handler that is expecting C or C-like calling behaviour with a 1:1 correspondence between parameters listed and parameters needed, you have to provide that C-like behavior. That means free functions or static methods with no hidden parameters.
And that means you can't assign a method to a function pointer without delving into assumptions about undefined behaviours.
But you can have a static method or free function invoke a method on an object if the object can be made available.
Given
void (*func)(void*)
Where the void *
is a pointer to user-provided control information, the simple solution is a static method or free function of the form
void handlerCaller(void* userp)
{
ISRHandlerClass * handlerp = (ISRHandlerClass *) userp;
handlerp->isrhandler(); // tiny bit may be lost here to subclass look-up
}
And
void isrhandler()
is implemented to do whatever the heck ISRHandlerClass
or child of ISRHandlerClass
needs to do.
You are pretty much stuck with handlerCaller
or something very much like it, so that's overhead you can't avoid. The rest depends on how general you want the ISR interface to be.
A simple generic ISR handler base class:
class ISRHandlerClass
{
public:
virtual ~ISRHandlerClass()
{
}
// pure virtual to be implemented by specialized handler
virtual void isrhandler() = 0;
};
and an equally simple implementer
class FooHandler: public ISRHandlerClass
{
public:
void isrhandler() //override tag if you've got 'em
{
// read Foo and store in buffer to be processed by lower priority task
}
};
But if you want to jettison generalization in favour of speed, don't bother with subclasses. You sacrifice space for multiple handler callers if you need more than one.
void FooHandlerCaller(void* userp)
{
FooHandler * handlerp = (FooHandler *) userp;
handlerp->isrhandler();
}
void BarHandlerCaller(void* userp)
{
BarHandler * handlerp = (BarHandler *) userp;
handlerp->isrhandler();
}
Or
template <class TYPE>
void handlerCaller(void* userp)
{
TYPE * handlerp = (TYPE *) userp;
handlerp->isrhandler();
}
usage
class FooHandler
{
public:
void isrhandler()
{
// read Foo and store in buffer to be processed by lower priority task
}
};
void (*func)(void*) = handlerCaller<FooHandler>;
FooHandler handler;
void* instance = (void *)&handler;
this
parameter that is probably tripping you up. A lot of useful information and tips here: isocpp.org/wiki/faq/pointers-to-members – user4581301