typedef void (*FuncPtrType)(); versus pointer to a class member function

I have created a class called CLongTimer - it is essentially a timer that counts down as you call a member function poll() in the main loop() function.

All it does is the

m_nTrigger = millis() + (nMin * 60 * 1000)

while (millis() < m_nTrigger)
{
}

thing.

It is a generic and conveniently re-useable solution to the problem of Timer1 etc being limited to about 8 seconds max.

Inside the class I have a pointer to a function of this type void (*FuncPtrType)() m_pFunc;.

When the trigger value is reached the function is called *m_pFunc();

It seems as though a global function of type void (*FuncPtrType)() works just fine.

But if I try and pass a void function that is the member of a class then all hell breaks loose.

When m_pFunc is de-referenced by my CLongTime object, it is being called on an invalid object.

This is clearly what is happening because Serial.println of various data members of my object reveal that they contain garbage.

So the question is how would one declare a function pointer type in a way that you can pass either a global void function or a void function that is the member of a class/object?

Is it possible?

LongTimer.cpp (1.64 KB)

LongTimer.h (1.08 KB)

Program.cpp (4.72 KB)

Program.h (987 Bytes)

ProgramStation.cpp (6.89 KB)

ProgramStation.h (1.68 KB)

When m_pFunc is de-referenced by my CLongTime object, it is being called on an invalid object.

Then, your code is wrong.

So the question is how would one declare a function pointer type in a way that you can pass either a global void function or a void function that is the member of a class/object?

Think about passing a member function, for a minute. Suppose you have a class called Dog, with a method called bark(). Suppose that you have:
Dog Spot;
Dog Fido;
Dog DoesNothingButClawTheFurniture;

Now, what are you going to pass to the function? Spot.bark()? Fido.bark()? Dog::bark()?

The ONLY what that you can pass a member function as a callback function is to make the member function static (shared by all instances of the class). Then, the static method needs to, somehow, decide which instance of the class is actually supposed to do something (by calling a non-static method on the correct instance).

If the class is a singleton (only one instance will ever exist; never more than one and never less than one), this is relatively simple. If the class is NOT a singleton (zero or more instances can exist at any given time), this is a lot more complex.

I always thought that there was one set of class functions but that they referred to different sets of data.

It appears that I have been making the wrong assumption - not that it has mattered up until this point until a tried to use function pointers.

I always thought that there was one set of class functions but that they referred to different sets of data.

When you create an instance of a class, the code is not actually duplicated. However, there is a big difference between a method that belongs to the instance (a normal method) and a method that belongs to the class (a static method).

It appears that I have been making the wrong assumption

I don't necessarily agree. I think that you may be making some invalid assumptions, but the solution is to understand the difference between static and non-static methods, and when each can be used and what data they can access.

PaulS:
When you create an instance of a class, the code is not actually duplicated. However, there is a big difference between a method that belongs to the instance (a normal method) and a method that belongs to the class (a static method).
I don't necessarily agree. I think that you may be making some invalid assumptions, but the solution is to understand the difference between static and non-static methods, and when each can be used and what data they can access.

I understood/understand the diff between static and non static function in so much as you can access data members with the latter but not the former.I obviously don't have a clear understanding of the difference when it comes to function pointers however.

You have a chunk of flash memory corresponding to a non-static class function.

And a chunk of memory is SRAM (or what ever it is called) corresponding to the data members associated with an instance of the class.

How are the two chunks of memory related to each other respect to the same function referencing a different data member associate with a different instance?

Perhaps if I can gain some insight into this I will better understand why a generic void function pointer won't work with this class member function.

There is one, and only one, copy of the code for any class, and it is shared by ALL instances of that class. Each instance of a class has it's own unique data. Class member functions know where their data is because they are passed a pointer to it (as a "hidden" first argument) when the function is called. A static member function does NOT receive that pointer, because there is no way to know which data to pass, since no class instance is referenced when calling a static function.

Regards,
Ray L.

RayLivingston:
There is one, and only one, copy of the code for any class, and it is shared by ALL instances of that class. Each instance of a class has it's own unique data. Class member functions know where their data is because they are passed a pointer to it (as a "hidden" first argument) when the function is called. A static member function does NOT receive that pointer, because there is no way to know which data to pass, since no class instance is referenced when calling a static function.

Regards,
Ray L.

Ahhhhh - that makes sense.

And when I dereference my function pointer that hidden parameter is not 'filled in' and could contain any old random pointer value....which is exactly what I observed when I tried to examine the contents of my data members!

The STL has std::bind() in the functional header, but it's not implemented for AVRs. It's far beyond you to try and port also since it's got some pretty advanced templating in it.

You might be able to achieve this though. It won't be anywhere near as flexible as the STL's function class, but it should do the trick.

The first trick is to modify your CLongTimer into a template. This not only gives it the flexibility to accept more than a single kind of function pointer, you can also use functors.

template<typename Func>
class CLongTimer
{
  ...
Func m_pFunc;
  ...
};

When you declare the timer in your code, you need to tell it what Func is going to be for that variable, like this: CLongTimer<void(*)(void)> debugPrinter;

But, as I said, we aren't limited to callback pointers with this approach. I mentioned functors before. A functor is simply a class that has operator() implemented. For calling member functions of an object, create a special wrapper functor for that class that is constructed from a pointer to the object, and implement operator() to call that function on the object pointer. Here's an example using PaulS's Dogs:

struct DogBarker
{
  explicit DogBarker( Dog *d ) : _d(d) {}
  void operator()() {if(_d) _d->bark();}
private:
  Dog* _d;
};

The double () is not a typo. The first pair is part of the operator name that tells the compiler which operator we're implementing (parentheses operator), and the second pair is the actual argument list (empty, in this case). Now we can do something like this:

Dog redRover;
DogBarker roverHowl(&redRover);

roverHowl();

You can "call" the object just like a function! And since it stores the pointer as a member variable, you can pass a copy of the functor into the templated CLongTimer and get exactly the behavior you want.

Dog Fido;
CLongTimer<DogBarker> FidoBarker(DogBarker(&Fido));  // or however you assign the "callback"

If you want more specific help templating you code, you'll need to post it.

Maybe you can create a abstract class FOO that has a virtual callback() method. Have your class derive from that class and declare the callback() method. Have a way to pass a class FOO pointer to your timer function instead of a function pointer for the callback.. Pass your object as a class FOO pointer and store that. When the timer expires, call fooPtr->callback(); That should call the object's callback() method with the right instance context.

johnwasser:
Maybe you can create a abstract class FOO that has a virtual callback() method. Have your class derive from that class and declare the callback() method. Have a way to pass a class FOO pointer to your timer function instead of a function pointer for the callback.. Pass your object as a class FOO pointer and store that. When the timer expires, call fooPtr->callback(); That should call the object's callback() method with the right instance context.

If you're going that route, why polymorphism? The only advantage that has over just passing the pointer to the derived class with the callback() method is so other things can inherit from FOO.

I prefer templating the timer class, since it gives more flexibility. You don't need to modify the class to support a virtual callback, you only need to create a trivial wrapper object.

Jiggy-Ninja:
The STL has std::bind() in the functional header, but it's not implemented for AVRs. It's far beyond you to try and port also since it's got some pretty advanced templating in it.

You might be able to achieve this though. It won't be anywhere near as flexible as the STL's function class, but it should do the trick.

The first trick is to modify your CLongTimer into a template. This not only gives it the flexibility to accept more than a single kind of function pointer, you can also use functors.

template<typename Func>

class CLongTimer
{
  ...
Func m_pFunc;
  ...
};




When you declare the timer in your code, you need to tell it what Func is going to be for that variable, like this: `CLongTimer<void(*)(void)> debugPrinter;`

But, as I said, we aren't limited to callback pointers with this approach. I mentioned functors before. A functor is simply a class that has operator() implemented. For calling member functions of an object, create a special wrapper functor for that class that is constructed from a pointer to the object, and implement operator() to call that function on the object pointer. Here's an example using PaulS's Dogs:


struct DogBarker
{
  explicit DogBarker( Dog d ) : _d(d) {}
  void operator()() {if(_d) _d->bark();}
private:
  Dog
_d;
};



The double () is **not** a typo. The first pair is part of the operator name that tells the compiler which operator we're implementing (parentheses operator), and the second pair is the actual argument list (empty, in this case). Now we can do something like this:


Dog redRover;
DogBarker roverHowl(&redRover);

roverHowl();



You can "call" the object just like a function! And since it stores the pointer as a member variable, you can pass a copy of the functor into the templated CLongTimer and get exactly the behavior you want.


Dog Fido;
CLongTimer FidoBarker(DogBarker(&Fido));  // or however you assign the "callback"



If you want more specific help templating you code, you'll need to post it.

But you would have to create a functor thingy for every object you wanted to call a particular function on?

I like the template class idea. That had not occurred to me and that is infinitely re-usable.

How do you declare a pointer to a function that is a member of a class?

Say I have a class CStation that contains a function void CStation::stop(){}
Then I have another class CProgram that contains an array of CStation objects.
And I want to set one of my CLongTimer objects with a pointer to the void CStation::stop() function for one of the Station objects in the array of them.
So that the 'station' is turned off when the timer expires.

At preset I had to create a global function void StopStation(){pStation-stop();} with a global pointer to one of my CStation objects from the array (pStation).
When I 'set' my CLongTimer object I give it a pointer to StopStation() and 'set' pStation with 'this'.
And then it all works but it is a bit of a hacky solution.

boylesg:
But you would have to create a functor thingy for every object you wanted to call a particular function on?

I like the template class idea. That had not occurred to me and that is infinitely re-usable.

Yes you would. Fortunately, like I showed you with the DogBarker struct, they're trivial. If you template the timer class properly, it won't be able to tell the difference if it's using a function pointer or a functor.

How do you declare a pointer to a function that is a member of a class?

You don't, that's what the functor is for. I tried doing some fudging around this but apparently there's a lot of complications: Standard C++

I would recommend not even trying.

Say I have a class CStation that contains a function void CStation::stop(){}
Then I have another class CProgram that contains an array of CStation objects.
And I want to set one of my CLongTimer objects with a pointer to the void CStation::stop() function for one of the Station objects in the array of them.
So that the 'station' is turned off when the timer expires.

Check the DogBarker class example I posted above. It does exactly what you need.

At preset I had to create a global function void StopStation(){pStation-stop();} with a global pointer to one of my CStation objects from the array (pStation).
When I 'set' my CLongTimer object I give it a pointer to StopStation() and 'set' pStation with 'this'.
And then it all works but it is a bit of a hacky solution.

I can't even follow that.

Like I said, if you want help making your timer class a template, post some code.

Jiggy-Ninja:
Like I said, if you want help making your timer class a template, post some code.

I have attached the relevant files to the original post - I don't think I need to attach the whole project.

This is my CLongTimer class declaration.

It has been a while but I more or less remember how to turn it into a template class - I might have to refresh my memory as to the exact syntax.

This is the syntax of declaring a pointer to a global function.

typedef void (*FuncPtrType)();

But what is the syntax of declaring a pointer to a function that is a member of a class?

I don't reckon I can deduce it from the above because the above did not seem all that intuitive to me.

typedef void (*FuncPtrType)();

class CLongTimer
{
  public:
    // Construction, destruction & initilisation
    CLongTimer();
    CLongTimer(const uint32_t nIntervalSec, const bool bRepetative, const FuncPtrType pCallBackFunc, const char* strOwnerName = "", const uint8_t nOwnerID = 0);
    ~CLongTimer();
    void set(const uint32_t nIntervalSec, const bool bRepetative, const FuncPtrType pCallBackFunc, const char* strOwnerName = "", const uint8_t nOwnerID = 0);
    int32_t poll();
    void restart(const bool bRepetative);
    bool isRunning()
    {
      return !m_bRepetative && (m_nTrigger > 0);
    }
    int32_t getRemMillis()
    {
      return m_nRemMills;
    }
    char* getRemTime();

    char* getOwnerName()
    {
      return m_strOwnerName.c_str();
    }

    uint8_t getOwnerID()
    {
      return m_nOwnerID;
    }

  protected:
    // Data
    uint32_t m_nIntervalMillis, m_nTrigger;
    int32_t m_nRemMills;
    bool m_bRepetative;
    FuncPtrType m_pCallBackFunc;
    String m_strOwnerName;
    uint8_t m_nOwnerID;
};

boylesg:
I have attached the relevant files to the original post - I don't think I need to attach the whole project.

My bad, didn't see that. I have a blind spot for attachments unless they're specifically mentioned. It looks quite well made.

It has been a while but I more or less remember how to turn it into a template class - I might have to refresh my memory as to the exact syntax.

In this case, it will be easy.

template<typename CallbackType>
class CLongTimer
{
  ...etc.

Then, anywhere you have FuncPtrType in the class declaration and functions, replace it with the template parameter CallbackType.

This is the syntax of declaring a pointer to a global function.

typedef void (*FuncPtrType)();

But what is the syntax of declaring a pointer to a function that is a member of a class?

I don't reckon I can deduce it from the above because the above did not seem all that intuitive to me.

I linked you a page about how to work with pointer-to-member-functions. I tried to use that info to make my own examples work, but I couldn't even get anything to compile properly. I keep getting a "must use '.' or '->' to call pointer-to-member function in..." even though that's exactly what I'm doing!!! If you want to try your own hand at it you're more than welcome. I attached the sketch I was testing with. If you're able to make it work I would love to know the solution.

Regardless of the syntax though, you cannot use a pointer-to-member-function on its own, you also need a pointer to the object you want to call it on. That's the impression I got from the isocpp website I posted the link for. You will still need a functor wrapper for it, but if you can figure out how to make member function pointers work you can make it much more generic.

It's trivial to create a functor wrapper for a fixed class and a fixed function call. It takes minutes to type up when you know what it needs. I'm going to assume you want to call stationOff() on your CProgramStation class with the timer. The basic functor wrapper you need is this:

struct ProgramStationStopper
{
  explicit ProgramStationStopper(CProgramStation* station) : _ptr(station) {}
  operator bool() const {return _ptr;}  // this is needed so that "if (m_pCallBackFunc)" in the timer class won't give a compile error.
  void operator()() { if(_ptr) _ptr->stationOff();} 
protected:
  CProgramStation* _ptr;
}

That's it. Then you just need to create a CLongTimer, pass it the ProgramStationStopper, and you're set.

sketch_aug29d.ino (716 Bytes)

You CANNOT create a pointer to a non-static class member function. c++ does not allow it.

Regards,
Ray L.

RayLivingston:
You CANNOT create a pointer to a non-static class member function. c++ does not allow it.

Regards,
Ray L.

That is demonstrably false, as I figured out the problem I had earlier (I needed to put parens around the whole object-member pair). The following example is not Arduino code but desktop C++ (trivial enough to convert:

#include <iostream>
#include <iomanip>

using namespace std;

const char bark1[] = "Yip yip!";
const char bark2[] = "Bow wow!";

struct Dog
{
  const char *sound;
  void bark() {cout << (sound) << endl;}
};
#define CALL_MEMBER_FN(object,ptrToMember)  ((object)->*(ptrToMember))
template<class T>
struct class_member_functor
{
  typedef void(T::*callback)(void);
  class_member_functor(T* ptr, callback member) : _ptr(ptr), _member(member) {}
  void operator()() {if(_ptr && _member) (_ptr->*_member)();}
  operator bool() const {return _ptr && _member;}
private:
  T* _ptr;
  callback _member;
};

int main(int argc, char** argv) 
{
 
  Dog yappy = {bark1};
  Dog bigboy = {bark2};
  
  yappy.bark();
  bigboy.bark();
  
  cout << endl;
  
  class_member_functor<Dog> yappybarker(&yappy, &Dog::bark);
  yappybarker();
 return 0;
}

You do need to pair it with a reference to the object though, so you need a wrapper over the pair to use it as a single function object.

The hiccup I've run into now is that const member functions are a different type, and I don't know if they can be converted to non-const. If I make another function in the Dog class with signature void whine() const, it won't fit in the same pointer as the non-const function void bark().

Honestly, you're probably best off using the fixed functor wrapper like I showed you with ProgramStationStopper.