Using class member function pointers in C++ for Arduino

1.8k views Asked by At

I need to make a list of function pointers to member objects and then execute them as need be in an InterruptSubRoutine. I created a class with a virtual function to wrap all classes that need interrupts, and they will use to execute their interrupt.

I can pass these and put them in the Array, but I get an error on the line where I try to execute them saying

expression must have a (pointer-to-) function type.

Header

 typedef bool (InterruptSubRoutine::*function_pointer)();
 void initializeTI();
 void enableTI();
 void disableTI();
 void procInterrupt();
 void addInterrupt(bool (InterruptSubRoutine::*interrupt)());

 TimerThree timerInt;
 function_pointer activeInterrupts[INTERRUPT_POINTER_SIZE];

Cpp

void ::initializeTI()
{
    timerInt.initialize(TIMER_INTERRUPT_PERIOD);
}

void ::procInterrupt()
{
    bool empty = true;
    for(int i = 0; i<INTERRUPT_POINTER_SIZE; i++)
    {
        if (activeInterrupts[i] != nullptr)
        {
            empty = false;
            bool returnV = activeInterrupts[i](); //this is where i get the problem, with the error stating "expression must have a (pointer-to-) function type"
            if (!returnV)
            {
                activeInterrupts[i] = nullptr;
            }
        }
    }
    if (empty)
    {
        disableTI();
    }
}

void ::addInterrupt(bool (InterruptSubRoutine::*function)())
{
    for(int i = 0; i<INTERRUPT_POINTER_SIZE; i++)
    {
        if (activeInterrupts[i] == nullptr)
        {
            activeInterrupts[i] = function;
            break;
        }
    }
}

void ::enableTI()
{
    void (*interrupt)(void);
    interrupt = &procInterrupt;
    timerInt.attachInterrupt(interrupt, TIMER_INTERRUPT_PERIOD);
}


void ::disableTI()
{
    timerInt.detachInterrupt();
}
2

There are 2 answers

0
Klaus On

Your problem starts with the wording of the question:

I need to make a list of function pointers to member objects...

No! You have pointer to member functions! And member functions need a object in which they are executed.

I created a class with a virtual function to wrap all classes that need interrupts

No! You create a base class where instances from derived classes ( which are called objects ) can use the given member functions. Please remember: The methods are part of the class but they are running in the context of the object.

Instead of that you also can have static class functions which are related to the class and work without objects! This is also possible but a total different approach.

From your wording I believe you did not really understand what is class,method,object and the relations between them. So I would advice you to read a OOP beginners book.

The simple problem as result of your wrong coding is, that you need an object in which context you can call the member function ( method ) which is addressed via a member function pointer.

If you want to store a object and a pointer, simply use a struct to fill the pointer and the object in and do the call. You are also free to bind the method pointer to the object with std::bind if you are using a modern c++11 version. As std::bind is header only code from c++ it works also for avr.

In general: I think it is a bad design for small embedded systems to create, register, and store objects and in addition pointers to functions in runtime! this all can be done during compile time which makes the code much faster, smaller and less error prone. Think about memory allocation ( new/malloc) on a small embedded device! And if you are already use static allocation and global objects ( which is also bad design in bigger projects ) you also can resolve your call tree to all objects during compile time.

As a simple fix for your first problem you should:

 bool returnV = (object.*activeInterrupts[i])();

where object is an instance of InterruptSubRoutine class or any derived class from that.

As an additional remark to your question itself: It would be nice to shrink down all code snippets to the minimum we need to analyze the problem. On the other hand it would be nice if it could be used to compile it directly without adding all the missing stuff. Thanks!

0
Pandrei On

here's something to get you started:

  • activeInterrupts is an array of function pointers function_pointer activeInterrupts[INTERRUPT_POINTER_SIZE]; hence activeInterrupts[i] will be a function pointer.
  • you can't assign a integer-type variable, a function pointer: bool returnV = activeInterrupts[i](), they are incompatible types