Go Down

Topic: Delegate system for member function pointers (Read 5420 times) previous topic - next topic

Aduen

Jan 12, 2012, 10:48 am Last Edit: Jan 12, 2012, 10:59 am by Aduen Reason: 1
Because I like programming in objects/classes, I got myself in a situation to use timers and callbacks. This is generally an issue in c++ (member function pointers)

I found this Delegate system that covers a whole lot (too much for standard Arduino programming)
http://www.codeproject.com/KB/cpp/FastDelegate.aspx

I works very nice, changed the SimpleTimer lib (Author: mromani@ottotecnica.com) to be used with this Delegate system.

What I was thinking, since Arduino programming is getting more and more professional on one-side, having a standard low-footprint Delegate system could be a nice addition.

I already got it working and the extra memory needed is very little, the guy who made it states that in most cases it would only compile to two lines of assembly. What still needs to be done is cutting it up (i guess 80% of the code could be discarded since Arduino uses a single compiler) and making it integegrate easy (without API breaks)

this is my compile output for a small program with this Delegate system:

With FastDelegate:

Code: [Select]
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:

Code: [Select]
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


Code as in test (working)

typedef
Code: [Select]
typedef FastDelegate0<> FuncDelegate;

Code in robot class:
Code: [Select]
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:
Code: [Select]
int SimpleTimer::setTimerDelg(long d, FuncDelegate f, int n){
    f();
}


Arduino prints TEST in the console


It all worked nice and fast, if it is not something to be used, mods may delete this post.

sixeyes

Could you post all the code you used?

I started reading the article over at Code Project but part way through my eyes glazed over. A complete example I could cut and paste into a sketch would be really useful.

So far I've used functors to achieve callbacks to member functions but this looks very interesting.

Iain

westfw

Quote
This is generally an issue in c++ (member function pointers)


How so?  What did making and setting a "delegate" gain me over the existing timer1 code that was simpler and smaller?
Code: [Select]
// a function to be executed periodically
void repeatMe() {
    Serial.print("Uptime (s): ");
    Serial.println(millis() / 1000);
}

void setup() {
    timer.setInterval(1000, repeatMe);
}

sixeyes

You've got to be using classes to want this. If you were, you'd know why it's useful.

Aduen

I am using it myself right now, so a fully working example wouldnt be a problem. I've also rewrote the SimpleTimer lib from
Code: [Select]
Author: mromani@ottotecnica.com using this system and some other advantages.

I'll make it a arduino lib with an example attached and post it for download in this thread. I'll try to get this done before the weekend.

@westfw: its for member function pointers, a simple function pointer wouldnt need a delegate system ofcourse. Although my current setup does all the magic in the background so you could easily throw in a simple function pointer or get more freaky and use a delegate for a member function pointer like so:

Code: [Select]
//no class
void simple_function(){
//do something
}

timerlib.setTimer(30000, simple_function, 0);

//within another class
delegate d = MakeDelegate(this, &BigClass::someFunction);

timerlib.setTimer(30000, d, 0);


With no changes in the timerlib object. This is ussually a hackle because non-member functions dont get a this operator, where member functions do get these. If your this operator gets screwed the called function has no clue whats going on in its own class/object.

But, I'll get back on this thread with some descent examples so its all getting a little clearer.

sixeyes


I'll make it a arduino lib with an example attached and post it for download in this thread. I'll try to get this done before the weekend.


Excellent. I look forward to trying it out.

Iain

westfw

Quote
its for member function pointers

"pointers to functions that are defined as part of a class" ?
Like: getting a pointer to digitalRead() is easy (because it's just a function), but getting a pointer to the function that implements Serial.write() would be difficult (because it's encapsulated inside the class)?

All these new-age terms!  "Delegate", "member", "class"!
Pretend I'm a dinosaur who's more familiar with "AOBJN", "JCL", and "Chaff." :-)

sixeyes

The problem is that "regular" C callbacks do not carry any state information. All class member functions have an implicit "this" parameter which means they can't be called by a C callback. Using delegates gets round the problem as it creates a callback that captures the "this" parameter.

It allows you to callback to a specific object. If you had a Mega with 4 serial ports in use, a C callback couldn't differentiate between the four serial ports but a delegate could, as it will capture the "this" parameter identifying which serial port it's related to.

Iain

westfw


Aduen

I've made it into a small library that you can unpack in the Arduino folder, I made it in 022, not 1.0. Have not tested it in 1.0 to (don't think it will work in the new one yet cause of the class differences) something for later on.

So, just unpack in the libraries folder of the arduino install, start/restart arduino software and you can look for it in the examples and libraries menu.

I did not made the delegate system API friendly yet but, its not that difficult as you will see in my code (kept it small). If it starts interesting more people I'll consider making the Delegate system more friendly.

http://img.aduen.nl/TimerLib.rar


fat16lib

Thanks for pointing out this article!  This clears up some mysteries for me.

I have been experimenting with C++ templates for Arduino libraries and believe better C++/object support is the future of embedded programming.

Many people think these methods are not viable for the 8-bit AVR, maybe they are right, but playing with new techniques is fun.

GreyGnome

Very useful indeed.  Thanks for posting.

kDodman

Great solution, a day of trying to figure this pointer crap out, and got it done in no time with this, once I figured out that you have to update his modified SimpleTimer.h to Arduino 1.0 by changing the <Wprogram.h> include to <Arduino.h>

Go Up