gfvalvo:
My question isn’t about attachInterrupt(). I simply want to provide a way to specify a class that has a call back feature for each instance. The call back function provided to each instance (either in the constructor or with an attach() method) happens to be an instance method of a different class rather than a "regular" function. Look at my pseudo code again:
Each instance of Class1 needs to be provided with a call back function. I want that call back function for instance1 (of Class1) to be the instanceFunction() of instance2 (of Class2).
Since both instances have identical functions (methods) I don't know what you gain unless you want to do something to A based on the state of B. I showed you how to perform just that.
if A and B both call the same callback, then as Paul mentioned, a static function works for that.
Putting that aside, and I understand there are other ways. My question remains, is it possible to do it the way I outlined in my pseudo code? I'm looking for any of the following:
"Yes."
"Yes, and here's how"
"No."
"No, and here's why"
"I don't know"
gfvalvo:
Putting that aside, and I understand there are other ways. My question remains, is it possible to do it the way I outlined in my pseudo code? I'm looking for any of the following:
"Yes."
"Yes, and here's how"
"No."
"No, and here's why"
"I don't know"
in C++11 (as far as I know) there is no way to get a pointer to a class member function.
There may be ways e.g. using Boost or other advanced C++ libraries, but you'd have to investigate that.
I cannot imagine a scenario where you would need a pointer to a member function, so for me my interest is academic.
If it is OK for Class1 to know the name of the desired instance function in Class2 then you can just store a reference to the instance, rather than a pointer to a function of that instance. This compiles, but I have not tried running it.
Yea. Some posts on SO and other places do purport to show a way of getting a pointer to an instance method. And, maybe this Boost thing will do it. But, they all seem convoluted at best.
So, once you resign yourself to that, you can move on to passing in an object reference as you an @Bulldog showed. To handle passing different classes, can go with Base / Derived class model or use templates.
Finally, just because I can, I’d then overload the () operator.
Doesn't that uniquely identify which function to call?
Unfortunately for you, that's not how member function pointers work.
Even more unfortunately, explaining how they work is not a trivial task. A lot of posts here are explaining why your ideas won't work, but there's precious few giving good alternatives.
There is a way to do what you want. The C++ Standard Template Library has a function<> template object in it that can store references to any callable function, and even a bind() function that lets you fix function arguments for a call (so you can bind a member function to a specific instance, for example). You can use a function<void(void)> object instead of a function pointer for much more versatility.
Unfortunately (sensing a theme here?), it doesn't look like the function class is implemented in the ArduinoSTL, at least not that I can see. Trust me when I saw that recreating that functionality will take significant amounts of template and polymorphism wizardry.
The easiest thing to do is to be a little more indirect. Rather than worry about binding the member function to the object instance directly in the function reference, create a normal function to wrap around that member call and give a pointer to that function to the ISR.
Foo* ZhuLi;
void setIntCallbackObjectReference( Foo* const bar )
{
ZhuLi = bar;
}
// give this function to your interrupt method.
void IntCallbackFunc()
{
// always test the pointer like this so you never dereference one that points to 0.
if( ZhuLi != 0 ) ZhuLi->DoTheThing();
}
Jiggy-Ninja:
There is a way to do what you want. The C++ Standard Template Library has a function<> template object in it that can store references to any callable function, and even a bind() function that lets you fix function arguments for a call (so you can bind a member function to a specific instance, for example). You can use a function<void(void)> object instead of a function pointer for much more versatility
The easiest thing to do is to be a little more indirect. Rather than worry about binding the member function to the object instance directly in the function reference, create a normal function to wrap around that member call and give a pointer to that function to the ISR.
// give this function to your interrupt method.
void IntCallbackFunc()
{
// always test the pointer like this so you never dereference one that points to 0.
if( ZhuLi != 0 ) ZhuLi->DoTheThing();
}
Thanks for your persistence, I think I understand now.
The only issue I have is that when I make the ISR static I cannot call any LoRaClass member functions which I need as the callback function is a member of the class.
If I use your first work-around and set callback as the ISR function rather than onDio0Rise, the users function will run within the interrupt, preventing other vital communication interrupts running while callback is operating.
Hence I need something like this with multiple functions to exit the interrupt as fast as possible and then to ensure that the users function (which could be anything) runs ok:
class MyCass{
public:
void(*userDefinedFunction); //A receive routine that is lengthy and must run every interrupt
void setupISR(void(*userDefinedFunction)){
attatchIntterupt(somePin, ISRFunction, RISING);
}
ISRFunction(){
MyCass::SomeFunction(); //A function to be called in order to exit the interrupt, but this function is itself a member of myClass so ISRFunction cannot be static
}
SomeFunction(){
//setup prior to userfunction
userDefinedFunction();
//checks after user function
};
myRXFunction(){
//do complex receive communication stuff
setup{
setupISR(myRXFunction);
}
The only issue is that the compiler is trying to force me to set the ISRFunction as static
bakerw71:
The only issue I have is that when I make the ISR static I cannot call any LoRaClass member functions which I need as the callback function is a member of the class.
go back to #8, if we only need one instance driven from one interrupt pin then all of the rest of the chatter is noise (which is not uncommon here).
If the class was designed as a singleton, then we wouldn't need to be having this conversation. Obviously, the class is (classes are) not designed with that restriction in mind.
PaulS:
Or, you modify the class to have a list of instances that are to respond, and the static callback calls the method of all the instances in the list.
Or uses some other internal / external criteria to determine which of the instance(s) it calls the method on.
BulldogLowell:
I know that, but it wasn't addressed in the example.
The issue is the instanceISR() in this example must be declared outside of a class, outside of the header in the .ino script otherwise the user of the library must edit the library every time the receive operation is modified rather than changing a function declared in the .ino.
gfvalvo:
Sure you can:
class myClass {
private:
static myClass *instanceIsrPointer;
static void staticISR() {
instanceIsrPointer->instanceISR();
}
void instanceISR() {
// Do ISR stuff here
}
#include "myClass.h"
myClass myInstance; //<<<<< Class instance created in .ino file just like you want.
void setup() {
myClass::begin(myInstance, 1);
}
void loop() {}