1

I've nine functions each of type void as follow:

void zero();
void one();
void two();
void three();
void four();
void five();
void six();
void seven();
void eight();
void nine();

I've put all these functions into an array pointer as follow (without any error):

typedef void (*num_func) ();
num_func functions[] = { zero, one, two, three, four, five, six, seven, eight, nine};

Now I'm writing an arduino library and wanting to achieve the same, but after hours of thinking I'm not able to achieve. Please help me how can I accomplish this in a library?

Thanks in advance.

  • @Mikael Sorry Mikael, I'm not able to comment at your answer (because stackexchange demands me to have 50 points before I can comment). Here is the error I'm getting from your implementation. storage class specified for 'functions' – Faraz Ahmad Feb 25 '16 at 22:44
  • What is your setup? I do not get that error. Obviously there must be some implementation of the functions and there must be a sketch that uses the library. – Mikael Patel Feb 25 '16 at 22:52
  • Yup, I've the implementation of the functions in .cpp file (for all of these zero() etc. functions). And also, I'm getting this error when I compile a sketch using that library. – Faraz Ahmad Feb 25 '16 at 22:54
  • Which line does to the compiler indicate? You have added some extra character or added extern also in the implementation. – Mikael Patel Feb 25 '16 at 22:58
  • It is pointing at: extern num_func functions[]; And I've NOT added extern in the implementation. – Faraz Ahmad Feb 25 '16 at 23:01
2

This was a bit fiddly to get right. I got inspiration from How do I create and use an array of pointer-to-member-function?

Based on my post about Function pointers / function callbacks / function variables I modified it to work with class functions:

class foo {

  public:

   void doAction0 ()
    {
      Serial.println (0);
    }

    void doAction1 ()
    {
      Serial.println (1);
    }

    void doAction2 ()
    {
      Serial.println (2);
    }

    void doAction3 ()
    {
      Serial.println (3);
    }

    void doAction4 ()
    {
      Serial.println (4);
    }

   // typedef for class function
   typedef void (foo::*GeneralFunction) ();

   // array of function pointers
    GeneralFunction doActionsArray [5] =
    {
      &foo::doAction0, 
      &foo::doAction1, 
      &foo::doAction2, 
      &foo::doAction3, 
      &foo::doAction4, 
    };

};  // end of class foo

void setup ()
{
  Serial.begin (115200);
  Serial.println ();
  Serial.println (F("Starting"));

  // test instance of foo
  foo bar;

  for (int i = 0; i < 5; i++)
    {
    // get member function pointer from array
    foo::GeneralFunction f = bar.foo::doActionsArray [i];
    // call the function
    (bar.*f) ();
    }  // end of for loop

}  // end of setup

void loop () { }

This compiles OK and prints:

Starting
0
1
2
3
4

Amended answer

I was wondering why you needed to specify bar in this line above:

    foo::GeneralFunction f = bar.foo::doActionsArray [i];

The reason is that the code above had the array as non-static, and thus a copy belonged to each instance of the class. This doesn't make a huge amount of sense, so the modified code below makes the array static and const. That is, the array should be the same for every instance of foo and also never change.

Modified code below:

class foo {

  public:

   void doAction0 ()
    {
      Serial.println (0);
    }

    void doAction1 ()
    {
      Serial.println (1);
    }

    void doAction2 ()
    {
      Serial.println (2);
    }

    void doAction3 ()
    {
      Serial.println (3);
    }

    void doAction4 ()
    {
      Serial.println (4);
    }

   // typedef for class function
   typedef void (foo::*GeneralFunction) ();

   static const GeneralFunction doActionsArray [5];

};  // end of class foo

 // array of function pointers
const foo::GeneralFunction foo::doActionsArray [5] =
  {
    &foo::doAction0, 
    &foo::doAction1, 
    &foo::doAction2, 
    &foo::doAction3, 
    &foo::doAction4, 
  };

void setup ()
{
  Serial.begin (115200);
  Serial.println ();
  Serial.println (F("Starting"));

  // test instance of foo
  foo bar;

  for (int i = 0; i < 5; i++)
    {
    // get member function pointer from array
    foo::GeneralFunction f = foo::doActionsArray [i];
    // call the function
    (bar.*f) ();
    }

}  // end of setup

void loop () { }

This will also save RAM, as the array of function pointers only exists once, not once per instance of the class.

  • See amended answer. The second method is a bit simpler and uses less RAM. – Nick Gammon Feb 27 '16 at 20:33
1

First you need a header file - let's say lib.h:

#ifndef LIB_H
#define LIB_H

typedef void (*num_func) ();
extern num_func functions[];

#endif

And then the implementation, lib.cpp:

#include "lib.h"

void zero();
void one();
void two();
void three();
void four();
void five();
void six();
void seven();
void eight();
void nine();

num_func functions[] = { zero, one, two, three, four, five, six, seven, eight, nine};

The functions could be declared as static (if you want to hide them) and they do need implementation. They are only forward declarations above. Below is a snippet of a sketch using the library (assuming that it is within the sketch folder).

#include "lib.h"

void setup()
{
  ...
}
void loop()
{
  ...
  // Call to the one() function
  functions[1]();
  ...
}

Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.