-
I am trying to use a member function in an interrupt. The function uses member variables so I created a global instance of that class to use it in a static function.
The problem is that I created a child class that should have the same interrupt. The interrupt is enabled in the constructor of the parent class, so it will be also enabled in the child class but with the wrong instance. -
To use the interrupt functions in both classes, I put them in a separate header file "Utilities.h" so that I can included it in both source files. But doing
void called_from_interrupt () { Instance_1.do_something(); }
requires including the class header, which will create multiple definitions errors.
I'll put a short example of what I am trying to do, the original code is really long.
parent_class.h :
#ifndef PARENT_CLASS_H
#define PARENT_CLASS_H
class parent_class {
public :
parent_class();
~parent_class();
void do_something();
};
extern parent_class instance_1;
#endif
parent_class.cpp :
#ifndef PARENT_CLASS_CPP
#define PARENT_CLASS_CPP
#define LIBCALL_ENABLEINTERRUPT
#define EI_ARDUINO_INTERRUPTED_PIN
#include "EnableInterrupt.h"
#include utilities.h
parent_class instance_1;
parent_class::parent_class() {
enableInterrupt(PIN_1, called_from_interrupt, FALLING);
}
parent_class::~parent_class() {}
parent_class::do_something() {
//manipulate some member variables
}
#endif
child_class.h :
#ifndef CHILD_CLASS_H
#define CHILD_CLASS_H
class child_class {
public :
child_class();
~child_class();
};
extern child_class instance_2;
#endif
child_class.cpp :
#ifndef CHILD_CLASS_CPP
#define CHILD_CLASS_CPP
#include utilities.h
child_class instance_2;
child_class::child_class() {}
child_class::~child_class() {}
#endif
utilities.h :
#ifndef UTILITIES_H
#define UTILITIES_H
#include "parent_class.h"
#define PIN_1 10
static void called_from_interrupt() {
instance_1.do_something();
}
#endif
Do you have please an elegant solution for that ?
Best Answer
Calling the static member of the base class should work.
You just have to make sure the
Instance
pointer is correct.This can be done with the singleton pattern.
Be aware of potential reentrancy risk with this approach though.
Example (disclaimer: I have not dealt with this exact problem before): https://godbolt.org/z/a6qj3c
Returns:
Now, big red flag, you can call
Child::run()
from two contexts. Your main thread and your interrupt routine. This means that Child::run() can be called while executing Child::run(), this a reentrancy problem.