Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callback function pointers C++ with/without classes

I got stuck. I am trying to form a function that will eat classless function pointers and ones from objects. Here is my current code that hopefully explains more.

(It should run on a Arduino, so I cannot use big libraries.)

First off, I am using this library for the Arduino:

/* SimpleTimer - A timer library for Arduino.
 * Author: [email protected]
 * Copyright (c) 2010 OTTOTECNICA Italy
 */

Which takes functions which it calls on a set timer interval of this type:

typedef void (*timer_callback)(void);

As far as my knowledge goes, it's a classles function, the webpage Pointers to member functions got me really far but, not far enough. Probably a terminology deficit on my side.

Now, I have made my own class which I would like in turn to use this SimpleTimer library. But if I feed the SimpleTimer my class functions, it does not like them (what I understand). But how would it be possible to make this happen without altering the SimpleTimer library.

So there is the class Robot, which has Robot::halt(). I want the robot to move forward for a set amount of time. Like so:

void Robot::forward(int speed, long time) {
    reset();
    timer.setTimer(time, c_func, 1);

    analogWrite(l_a, speed);
    analogWrite(r_a, speed);
    isMoving(true);
}

void Robot::halt() {
    __isMoving = false;
    digitalWrite(r_a, LOW);
    digitalWrite(r_b, LOW);
    digitalWrite(l_b, LOW);
    digitalWrite(l_a, LOW);
}

The c_func variable is a classless function at this point, but I would like to use the Robot::halt function. I have looked, read, learned but haven't succeeded yet. I just can't seem to wrap my head around this one because I am missing some angle.

I tried:

timer.setTimer(time, (this->*halt), 1);
timer.setTimer(time, Robot::*halt, 1);
timer.setTimer(time, &Robot::halt), 1);

But it would all amount to the same problem/ me just stabbing in the dark here...

EDIT

Earlier, I said not wanting to change the SimpleTimer library code. I want to comeback on this one, I guess altering it there would be the better option.

Thanks for all the current answers already, I was only allowed to flag one as a viable answer, actually everyhting I read here was extremely helpful.

To continue this, changing the SimpleTimer code. This class needs to have a reference to the object that holds my "halt" function, right? So, overloading the settimer function to something that takes my object and my function as two seperate pointers would work...? I think I am getting the hang of this but, I am not there yet with my head.

EDIT

I don't know who came with this one again but, anyone finding this thread. If found Member Function Pointers and the Fastest Possible C++ Delegates to give a very nice introduction in function pointers and member function pointers.

EDIT

Got it working, changed the SimpleTimer library to use this Delegate system: http://www.codeproject.com/KB/cpp/FastDelegate.aspx

It integrated very nicely, and it could be nice to have a standard Delegate system like this in the Arduino library.

Code as in test (working)

typedef

typedef FastDelegate0<> FuncDelegate;

Code in robot class:

void Robot::test(){
    FuncDelegate f_delegate;
    f_delegate = MakeDelegate(this, &Robot::halt);

    timer.setTimerDelg(1, f_delegate, 1);
}

void Robot::halt() {
    Serial.println("TEST");
}

Code in SimpleTimer class:

int SimpleTimer::setTimerDelg(long d, FuncDelegate f, int n){
    f();
}

Arduino prints TEST in the console.

Next step putting it in an array, don't see a lot of problems there. Thanks everyone, I can't believe the stuff I learned in two days.

What's that smell? Is that the smell of...? Success!

For the ones interested, the used Delegate system does not amount to memory capacity issues: With FastDelegate

AVR Memory Usage
----------------
Device: atmega2560

Program:   17178 bytes (6.6% Full)
(.text + .data + .bootloader)

Data:       1292 bytes (15.8% Full)
(.data + .bss + .noinit)


Finished building: sizedummy

Without FastDelegate:

AVR Memory Usage
----------------
Device: atmega2560

Program:   17030 bytes (6.5% Full)
(.text + .data + .bootloader)

Data:       1292 bytes (15.8% Full)
(.data + .bss + .noinit)


Finished building: sizedummy
like image 571
Aduen Avatar asked Jan 11 '12 12:01

Aduen


People also ask

Is callback a function pointer?

In simple language, If a reference of a function is passed to another function as an argument to call it, then it will be called as a Callback function. In C, a callback function is a function that is called through a function pointer.

How do you write a callback function in C?

Example Code #include<stdio. h> void my_function() { printf("This is a normal function."); } void my_callback_function(void (*ptr)()) { printf("This is callback function.

What is the difference between function pointer and callback functions?

Difference between Function Pointer and Callback FunctionsA function pointer is a pointer that points to the function. Whereas, callback functions are function pointers passed as parameters of the function, which can be called back when an event occurs.

What is the advantage of callback function in C?

The main advantage of using callbacks is that you can call a subroutine defined in higher software level from a lower software level subroutine.


1 Answers

You can do this by making a functor object, that acts as a proxy between the timer code and your code.

class MyHaltStruct
{
public:
    MyHaltStruct(Robot &robot)
        : m_robot(robot)
        { }

    void operator()()
        { robot.halt(); }

private:
    Robot &m_robot;
}

// ...

timer.setTimer(time, MyHaltStruct(*this), 1);

Edit

If it can't be done via a functor object, you could global variables and functions instead, maybe in a namespace:

namespace my_robot_halter
{
    Robot *robot = 0;

    void halt()
    {
        if (robot)
            robot->halt();
    }
}

// ...

my_robot_halter::robot = this;
timer.setTimer(time, my_robot_halter::halt, 1);

This only works if you have one robot instance though.

like image 52
Some programmer dude Avatar answered Oct 15 '22 23:10

Some programmer dude