user7123: I want to write a class that allows the user to attach his own function to a member function that listens for messages coming from a wireless module, so that the user's function can be called depending on the message.
I am thinking about using function pointers but I don't know how it will work since I don't know the user's function parameters, return type and number of functions that will be added.
//sketch.ino

<unknown> (*funcPtr)(<unknown>)[<unknown>];

void receive() {
  message.type = 'o';
  if (message.available()) {
    message.receive();
  }
  switch (message.type) {
    case 'p': {
      Serial.println(p);
      break;
    }
    case 'f': {
      funcPtr[message.funcID](message.parameter1, message.parameter2);
      break;
    }
    default: break;
}

void userFunction1() {
  Serial.println("User function 1");
}

int userFunction2(int x) {
  return x * 2;
}

funcPtr[0] = &userFunction1;
funcPtr[1] = &userFunction2;

void setup() {}

void loop() {
  receive();
}

Is this kind of thing possible?

user10794: You can't call arbitrary functions (with random return types, and any number of arguments) but you can specify a callback function that takes a certain number of specific arguments, and returns a certain thing (or nothing).
See http://www.gammon.com.au/callbacks
Example code:
typedef void (*GeneralMessageFunction) ();

void sayHello ()
  {
  Serial.println ("Hello!");  
  }  // end of sayHello

void sayGoodbye ()
  {
  Serial.println ("Goodbye!");  
  }  // end of sayGoodbye

void checkPin (const int pin, GeneralMessageFunction response); // prototype

void checkPin (const int pin, GeneralMessageFunction response)
  {
  if (digitalRead (pin) == LOW)
     {
     response ();  // call the callback function
     delay (500);  // debounce
     }
  }  // end of checkPin

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  pinMode (8, INPUT_PULLUP);
  pinMode (9, INPUT_PULLUP);
  }  // end of setup

void loop ()
  {
  checkPin (8, sayHello);    
  checkPin (9, sayGoodbye);
  }  // end of loop



I don't know how it will work since I don't know the user's function parameters, return type and number of functions that will be added.

You will need to tell the user what sort of function to write. For example, a function that takes a string (ie. the message) and returns a boolean (whether it was handled or not).

user7508: 
I don't know the user's function parameters,

A common way for dealing with this issue is to pass a generic pointer to
arbitrary data. See below.

return type

It makes little sense to allow for arbitrary return types, as your
library would have no way of knowing what to do with the returned value.

and number of functions that will be added.

Either you allocate the callback array statically with a fixed size, or
you use dynamic allocation. In the first case, the array size could be
decided by the user if it is a template parameter. In the second case,
you risk memory fragmentation unless all the callbacks are registered
once and for all at program startup, which is a common scenario anyway.

About the generic pointer technique
This is a very common way of defining callbacks in C: a callback
contains both a function and a void * pointer to arbitrary data, which
will be given as a parameter to the function. It is up to the user to
decide if and how he will use this pointer: he could completely ignore
it, like he could make it point to the root of a complex data tree.
Here is a simple example:
// A callback contains both a function and a pointer to arbitrary data
// that will be passed as argument to the function.
struct Callback {
    Callback(void (*f)(void *) = 0, void *d = 0)
        : function(f), data(d) {}
    void (*function)(void *);
    void *data;
};

Callback callbacks[3];

// This callback expects an int.
void print_int(void *data)
{
    int parameter = * (int *) data;
    Serial.println(parameter);
}

// This one expects a C string.
void print_string(void *data)
{
    char * parameter = (char *) data;
    Serial.println(parameter);
}

void setup()
{
    Serial.begin(9600);

    // Register callbacks.
    static int seventeen = 17;
    static int forty_two = 42;
    static char hello[] = "Hello, World!";
    callbacks[0] = Callback(print_int, &seventeen);
    callbacks[1] = Callback(print_int, &forty_two);
    callbacks[2] = Callback(print_string, hello);
}

void loop()
{
    // Test all the callbacks.
    for (size_t i = 0; i < 3; i++)
        callbacks[i].function(callbacks[i].data);
    delay(500);
}

Notice that the two callback functions take different types of
parameters, only disguised into the same generic pointer. Notice also
that print_int is used in two different callbacks with different data.
In this example, the data does not change, but this need not be the
case: both the callbacks and the rest of the user code could change the
data pointed to by the generic pointers. Again, it is up to the user to
decide how he will use this facility to communicate between his
callbacks and the rest of his code.

7123: <p>I want to write a class that allows the user to attach his own function to a member function that listens for messages coming from a wireless module, so that the user's function can be called depending on the message.</p>

<p>I am thinking about using function pointers but I don't know how it will work since I don't know the user's function parameters, return type and number of functions that will be added.</p>

<pre><code>//sketch.ino

&lt;unknown&gt; (*funcPtr)(&lt;unknown&gt;)[&lt;unknown&gt;];

void receive() {
  message.type = 'o';
  if (message.available()) {
    message.receive();
  }
  switch (message.type) {
    case 'p': {
      Serial.println(p);
      break;
    }
    case 'f': {
      funcPtr[message.funcID](message.parameter1, message.parameter2);
      break;
    }
    default: break;
}

void userFunction1() {
  Serial.println("User function 1");
}

int userFunction2(int x) {
  return x * 2;
}

funcPtr[0] = &amp;userFunction1;
funcPtr[1] = &amp;userFunction2;

void setup() {}

void loop() {
  receive();
}
</code></pre>

<p>Is this kind of thing possible?</p>
 10794: <p>You can't call <strong>arbitrary</strong> functions (with random return types, and any number of arguments) but you can specify a callback function that takes a certain number of specific arguments, and returns a certain thing (or nothing).</p>

<p>See <a href="http://www.gammon.com.au/callbacks" rel="nofollow">http://www.gammon.com.au/callbacks</a></p>

<p>Example code:</p>

<pre><code>typedef void (*GeneralMessageFunction) ();

void sayHello ()
  {
  Serial.println ("Hello!");  
  }  // end of sayHello

void sayGoodbye ()
  {
  Serial.println ("Goodbye!");  
  }  // end of sayGoodbye

void checkPin (const int pin, GeneralMessageFunction response); // prototype

void checkPin (const int pin, GeneralMessageFunction response)
  {
  if (digitalRead (pin) == LOW)
     {
     response ();  // call the callback function
     delay (500);  // debounce
     }
  }  // end of checkPin

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  pinMode (8, INPUT_PULLUP);
  pinMode (9, INPUT_PULLUP);
  }  // end of setup

void loop ()
  {
  checkPin (8, sayHello);    
  checkPin (9, sayGoodbye);
  }  // end of loop
</code></pre>

<hr>

<blockquote>
  <p>I don't know how it will work since I don't know the user's function parameters, return type and number of functions that will be added.</p>
</blockquote>

<p>You will need to tell the user what sort of function to write. For example, a function that takes a string (ie. the message) and returns a boolean (whether it was handled or not).</p>
 7508: <blockquote>
  <p>I don't know the user's function parameters,</p>
</blockquote>

<p>A common way for dealing with this issue is to pass a generic pointer to
arbitrary data. See below.</p>

<blockquote>
  <p>return type</p>
</blockquote>

<p>It makes little sense to allow for arbitrary return types, as your
library would have no way of knowing what to do with the returned value.</p>

<blockquote>
  <p>and number of functions that will be added.</p>
</blockquote>

<p>Either you allocate the callback array statically with a fixed size, or
you use dynamic allocation. In the first case, the array size could be
decided by the user if it is a template parameter. In the second case,
you risk memory fragmentation unless all the callbacks are registered
once and for all at program startup, which is a common scenario anyway.</p>

<hr>

<h2>About the generic pointer technique</h2>

<p>This is a very common way of defining callbacks in C: a callback
contains both a function and a <code>void *</code> pointer to arbitrary data, which
will be given as a parameter to the function. It is up to the user to
decide if and how he will use this pointer: he could completely ignore
it, like he could make it point to the root of a complex data tree.</p>

<p>Here is a simple example:</p>

<pre><code>// A callback contains both a function and a pointer to arbitrary data
// that will be passed as argument to the function.
struct Callback {
    Callback(void (*f)(void *) = 0, void *d = 0)
        : function(f), data(d) {}
    void (*function)(void *);
    void *data;
};

Callback callbacks[3];

// This callback expects an int.
void print_int(void *data)
{
    int parameter = * (int *) data;
    Serial.println(parameter);
}

// This one expects a C string.
void print_string(void *data)
{
    char * parameter = (char *) data;
    Serial.println(parameter);
}

void setup()
{
    Serial.begin(9600);

    // Register callbacks.
    static int seventeen = 17;
    static int forty_two = 42;
    static char hello[] = "Hello, World!";
    callbacks[0] = Callback(print_int, &amp;seventeen);
    callbacks[1] = Callback(print_int, &amp;forty_two);
    callbacks[2] = Callback(print_string, hello);
}

void loop()
{
    // Test all the callbacks.
    for (size_t i = 0; i &lt; 3; i++)
        callbacks[i].function(callbacks[i].data);
    delay(500);
}
</code></pre>

<p>Notice that the two callback functions take different types of
parameters, only disguised into the same generic pointer. Notice also
that <code>print_int</code> is used in two different callbacks with different data.
In this example, the data does not change, but this need not be the
case: both the callbacks and the rest of the user code could change the
data pointed to by the generic pointers. Again, it is up to the user to
decide how he will use this facility to communicate between his
callbacks and the rest of his code.</p>
