1
votes

For a real time embedded system I'm trying to provide an interrupt handler, which allows for registering any non-static method pointer (as well as the object's instance of course), which gets called, when the interrupt occurs.

In C, this was easy to do, e.g.:

void (*func)(void*) = 0; // <- method to be called goes here
void* instance;          // <- instance for this-call goes here

void InterruptHandler()
{
  func(instance);
}

Afaik, this meets the this-call C++ does implicitly when calling a non-static method.

However, the C++ the compiler refuses to cast a method pointer to a function pointer (at least I found no way to do so) - which surely is comprehensible, but kind of counterproductive in my case.

Is there any way to directly emulate the C++ this-call like in C? I'm aware of delegates, however my compiler is limited to C++98, no boost library, etc; and even custom lightweight implementations, e.g. Sergey Ryazanov's Impossibly Fast C++ Delegates, provide a certain overhead I'd like to avoid if possible.

1
Methods always have a hidden this parameter that is probably tripping you up. A lot of useful information and tips here: isocpp.org/wiki/faq/pointers-to-membersuser4581301

1 Answers

2
votes

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;