Pages: [1]   Go Down
Author Topic: A link to info on 'function pointers'  (Read 452 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

http://www.newty.de/fpt/index.html

I discovered this site today and found it useful.

One example I got running on Arduino:
 [edit: Oops, From another site http://www.codeterrorizer.com/cc/using-function-pointers-function-pointer-part-ii]
Code:
#include <stdio.h>
#include <Serial.h>

/**
 * Using a function pointer in a structure.
 */
struct _Object {
    void (* functionPointer)();
    int value;
};
 
/**
 * Passing a function pointer to a function.
 */
void passFunction(void (* functionPointer)()) {
    /* call our passed function */
    functionPointer();
}
 
void testFunction() {
    Serial.println("hello");
}
 
void testFunction2() {
    Serial.println("juhu");
}
 
void setup() {
    Serial.begin(9600);

    /* pointer to void function with no parameters myFunction */
    void (* myFunctionPointer)() = testFunction;
    /* call original function */
    Serial.print("#1 ");
    testFunction();
    /* call our new pointer function */
    Serial.print("#2 ");
    myFunctionPointer();
 
    /* create struct */
    struct _Object Object;
    Object.value = 1;
    Object.functionPointer = testFunction;
 
    Serial.print("#3 ");
    printf("%d\n", Object.value);
    Serial.print("#4 ");
    Object.functionPointer();
 
    /* Add function pointer to our gobal array. */
    int functionPointers[2];
 
    functionPointers[0] = (int)testFunction;
    Serial.print("#5 ");
    printf("%d\n", functionPointers[0]);
 
    functionPointers[1] = (int)testFunction2;
    printf("%d\n", functionPointers[1]);
 
    /* Creepy! but possible. */
    Serial.print("#6 ");
    ((void (*)()) functionPointers[0])();
    Serial.print("#7 ");
    ((void (*)()) functionPointers[1])();
 
}

void loop() {
  // put your main code here, to run repeatedly:
  
}

Interesting, though, cases #3 and #5 do not appear to call the function (neither 'hello' nor 'juhu' is printed).

[edit, again]
I compiled the example as a Win32 console app (to see what it presumably SHOULD do) and get this output, indicating the Arduino incarnation has 'problems':

hello
hello
1
hello
19665356
19665151
hello
juhu

[edit: Still reading?  OK, I changed the example so it appears to work the same as in Win32]

Code:
#include <stdio.h>
#include <Serial.h>

/**
 * Using a function pointer in a structure.
 */
struct _Object {
    void (* functionPointer)();
    int value;
};
 
/**
 * Passing a function pointer to a function.
 */
void passFunction(void (* functionPointer)()) {
    /* call our passed function */
    functionPointer();
}
 
void testFunction() {
    Serial.println("hello");
}
 
void testFunction2() {
    Serial.println("juhu");
}
 
void setup() {
    Serial.begin(9600);

    /* pointer to void function with no parameters myFunction */
    void (* myFunctionPointer)() = testFunction;
    /* call original function */
    Serial.print("#1 ");
    testFunction();
   
    /* call our new pointer function */
    Serial.print("#2 ");
    myFunctionPointer();
 
    /* create struct */
    struct _Object Object;
    Object.value = 1;
    Object.functionPointer = testFunction;
 
    Serial.print("#3 ");
    Serial.println(Object.value);
   
    Serial.print("#4 ");
    Object.functionPointer();
 
    /* Add function pointer to our gobal array. */
    int functionPointers[2];
 
    functionPointers[0] = (int)testFunction;
    Serial.print("#5 ");  ////////////////////////////////////// Changed
    Serial.println(functionPointers[0]);
 
    functionPointers[1] = (int)testFunction2;
    Serial.print("#6 ");  ////////////////////////////////////// Changed
    Serial.println(functionPointers[1]);
 
    /* Creepy! but possible. */
    Serial.print("#7 ");
    ((void (*)()) functionPointers[0])();
   
    Serial.print("#8 ");
    ((void (*)()) functionPointers[1])();
 
}

void loop() {
  // put your main code here, to run repeatedly:
 
}

and this prints out:

#1 hello
#2 hello
#3 1
#4 hello
#5 103
#6 96
#7 hello
#8 juhu
« Last Edit: December 12, 2013, 08:20:50 pm by JohnHoward » Logged

UK
Offline Offline
Shannon Member
****
Karma: 222
Posts: 12562
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Interesting, though, cases #3 and #5 do not appear to call the function (neither 'hello' nor 'juhu' is printed).

That's because you never actually call the pointed-to function in either of those cases.

Storing function pointers as ints is wrong. Don't do it, even on platforms where ints happens to be the same size as function pointers. If you want an array of function pointers, declare an array of function pointers.

I can't match up the output you presented with the code and I guess this was not the actual output of the code you posted. In light of the comments above, is there any part of the behaviour of your sketch that you still think is wrong?
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeah, got the numbering wrong as I was experimenting and exploring.  The 2nd variant of my code seems to do what it's supposed to do.  Or at least mirrors what the original author's example does when I compile it in Visual Studio and run that.

The two I thought were problematic seem to print out the address or value of the pointer, not the output of the two functions, if I'm understanding correctly now.  As you say, the functions aren't called.

Hopefully it's useful info for the rather frequent questions here about pointers.  I recall one person asking to make an array of function pointers, which this example also happens to illustrate.

It made some concepts clearer for my pointer-phobic brain.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I cleaned up your code a bit. One of the reasons things weren't printing was that you were mixing printf with Serial.print.

Modified version:

Code:
typedef void (* myFunctionPointer) ();

/**
 * Using a function pointer in a structure.
 */
typedef struct myObject {
  myFunctionPointer functionPointer;
  int value;
};

/**
 * Passing a function pointer to a function.
 */
void passFunction(myFunctionPointer functionPointer) ;

void passFunction(myFunctionPointer functionPointer) {
  /* call our passed function */
  functionPointer();
}

void testFunction() {
  Serial.println("hello");
}

void testFunction2() {
  Serial.println("juhu");
}

myFunctionPointer functionPointers[2];

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

  /* pointer to void function with no parameters myFunction */
  myFunctionPointer functionPointer = testFunction;
 
  /* call original function */
  Serial.print("#1 ");
  testFunction();
 
  /* call our new pointer function */
  Serial.print("#2 ");
  functionPointer();

  /* create struct */
  myObject Object;
  Object.value = 1;
  Object.functionPointer = testFunction;

  Serial.print("#3 ");
  Serial.println(Object.value);
  Serial.print("#4 ");
  Object.functionPointer();


  functionPointers[0] = testFunction;
  Serial.print("#5 ");
  Serial.println((int) functionPointers[0]);

  functionPointers[1] = testFunction2;
  Serial.println((int) functionPointers[1]);

  /* Creepy! but possible. */
  Serial.print("#6 ");
  functionPointers[0] ();
  Serial.print("#7 ");
  functionPointers[1] ();

}

void loop() {
  // put your main code here, to run repeatedly:
}

Output:

Code:
#1 hello
#2 hello
#3 1
#4 hello
#5 103
96
#6 hello
#7 juhu
Logged

Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nick, I think you missed the intent of the originator of that code example -- to examine possible alternatives for declaring pointers to functions.  'Creepy' but valid; impractical perhaps but instructive, brain stretchers for the learners.

Cleaned up is better, though.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, yes?

Here's another way. Function objects:

Code:
// function object
typedef struct myObject
  {
  // constructor
  myObject (const int value) : value_ (value) {}
  // operator ()
  void operator () (void)
    {
    Serial.print ("Value = ");
    Serial.println (value_);
    }  // end of operator ()

  private:    
    int value_;
};

void setup()
  {
  Serial.begin(115200);
  myObject obj1 (42);
  myObject obj2 (22);
  myObject obj3 (55);
 
  // call the function objects
  obj1 ();
  obj2 ();
  obj3 ();
}

void loop() { }

Output:

Code:
Value = 42
Value = 22
Value = 55

In this case the object "behaves like" a function, except you can hold private variables (state). Quite a useful trick if you want multiple copies of a function that do the same thing but "remember" things between function calls.
Logged

Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Clever fellow!  I must digest more fully, but much like I often do with passing anonymous functions in javascript.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 222
Posts: 12562
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think it's closer to creating a closure in Javascript.
« Last Edit: December 13, 2013, 09:45:09 pm by PeterH » Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Correct, I used the wrong term.
Logged

Pages: [1]   Go Up
Jump to: