BulldogLowell:
Yes and stored them in an array of a different kind of pointer!
... which the compiler allowed due to >:( >:( >:( -fpermissive >:( >:( >:(.
BulldogLowell:
Yes and stored them in an array of a different kind of pointer!
... which the compiler allowed due to >:( >:( >:( -fpermissive >:( >:( >:(.
oqibidipo:
... which the compiler allowed due to >:( >:( >:( -fpermissive >:( >:( >:(.
And without -fpermissive you are saying the code wouldn't compile?
fun0.cc
#include <stdint.h>
static void nothing(void) {};
typedef void (*voidFuncPtr)(uint32_t,uint32_t,uint32_t);
voidFuncPtr PinCB1[] = {nothing, nothing, nothing};
Without -fpermissive:
fun0.cc:5:50: error: invalid conversion from 'void (*)()' to 'voidFuncPtr {aka void (*)(long unsigned int, long unsigned int, long unsigned int)}' [-fpermissive]
voidFuncPtr PinCB1[] = {nothing, nothing, nothing};
oqibidipo:
fun0.cc#include <stdint.h>
static void nothing(void) {};
typedef void (*voidFuncPtr)(uint32_t,uint32_t,uint32_t);
voidFuncPtr PinCB1[] = {nothing, nothing, nothing};
Without -fpermissive:fun0.cc:5:50: error: invalid conversion from 'void ()()' to 'voidFuncPtr {aka void ()(long unsigned int, long unsigned int, long unsigned int)}' [-fpermissive]
voidFuncPtr PinCB1[] = {nothing, nothing, nothing};
Thank you
I see the need for this. The question is now hot to initialize my array with null values so I can test each?
Example:
[if (PinCB[Pin]) { // test to see if a function is assigned
PinCB[Pin](Time,PinsChanged,Pins);
}
Z
You can start by creating an array of the same type you wish it to contain.
BulldogLowell:
You can start by creating an array of the same type you wish it to contain.
so your saying that changing the code to this is more appropriate?
static void nothing(uint32_t,uint32_t,uint32_t) {};
typedef void (*voidFuncPtr)(uint32_t,uint32_t,uint32_t);
voidFuncPtr PinCB1[] = {nothing, nothing, nothing};
Yes, that will work.
Interestingly, this also works:
static void nothing(void) {}
static void nothing(uint32_t,uint32_t,uint32_t) {}
typedef void (*voidFuncVoidPtr)(void);
typedef void (*voidFunc3u32Ptr)(uint32_t,uint32_t,uint32_t);
voidFuncVoidPtr PinCB1[] = { nothing, nothing, nothing };
voidFunc3u32Ptr PinCB2[] = { nothing, nothing, nothing };
The correct version of nothing(...) is used for each array.
oqibidipo:
Yes, that will work.Interestingly, this also works:
static void nothing(void) {}
static void nothing(uint32_t,uint32_t,uint32_t) {}
typedef void (*voidFuncVoidPtr)(void);
typedef void (*voidFunc3u32Ptr)(uint32_t,uint32_t,uint32_t);
voidFuncVoidPtr PinCB1[] = { nothing, nothing, nothing };
voidFunc3u32Ptr PinCB2[] = { nothing, nothing, nothing };
The correct version of nothing(...) is used for each array.
This makes absolute sense. thank you I have altered my code to match and it continues to function properly ![]()
Sorry OP @Fuzzyzilla I feel like I hijacked your post a little even though this is all related to Arrays of function pointers and Lambda ![]()
Were you able to get all your Questions answered?
Z
Thanks so much! So I can treat lamdas just as if they were functions of the same type?!
Can I initialize an array with lamdas?
Also, you could initialize your array with all NULL, which wouldn't be a problem(might even save memory). You'd have to check if the reference is ==NULL before you call it though. This is the method I use in my function pointer arrays (I have 4 seperate arrays in my program
).
voidFuncVoidPtr PinCB1[] = {
nothing,
nothing,
[](){},
[](){
something();
},
[](){
something();
somethingElse(42, 175);
},
nothing
};
That empty lambda looks so cute... ![]()
oqibidipo:
voidFuncVoidPtr PinCB1[] = {
nothing,
nothing,
{},
{
something();
},
{
something();
somethingElse(42, 175);
},
nothing
};
That empty lambda looks so cute... :P
I love it!! This Thread is so entertaining [ ] ( ) { } I never thought of using an empty lambda to initialize an array! ![]()
Z
The "space saving" part was code length, not memory usage
I don't understand how you expect it to save any code space. Isn't a lambda just an unnamed function? It still takes up the same amount of space as a named function would, doesn't it? (with, IMO, less clarity.)
westfw:
I don't understand how you expect it to save any code space. Isn't a lambda just an unnamed function? It still takes up the same amount of space as a named function would, doesn't it? (with, IMO, less clarity.)
I like it for simple things that happen only during specific events for example this my high speed tachometer using an encoder with 400 pulses per revolution (only using clock pin):
#define interruptPin 2
volatile int Counts = 400; // count per revolution
volatile unsigned long timeX = 1;
volatile unsigned long LastTime;
volatile int PulseCtrX;
unsigned long MicroS_in_One_Minute = 60000000;
void setup() {
Serial.begin(115200);
// attach interrupt to encoder with 400 pulses per revolution
attachInterrupt(digitalPinToInterrupt(interruptPin), []() {
static int Ctr;
unsigned long Time;
Ctr++;
if (Ctr >= Counts) { // decrease the number pulses used.
Time = micros();
timeX += (Time - LastTime); // this time is accumulative ovrer those "Counts" readings
LastTime = Time;
PulseCtrX ++; // will usually be 1 unless something else delays the sample
Ctr = 0;
}
}, FALLING);
}
void loop() {
// Other code to handle tachometer input
if (PulseCtrX) {
static unsigned long SpamTimer;
if ((millis() - SpamTimer) >= (100)) {
SpamTimer = millis();
Serial.print(MicroS_in_One_Minute / timeX);
Serial.println("RPM");
}
PulseCtrX = 0;
}
}
The attach interrupts and the code associated with it are together and not scattered somewhere else.
Z
That's a good example of how a Lambda can be put to use.
Attaching them to some array of function pointers where the respective anonymous functions are defined in yet Amo ther unattached and un-referenced function (i.e. your other example) would at best be an academic exercise but in use... well... not particularly useful at all.
Defining the respective functions, naming them with useful monikers, and assembling them into a usefully named array is by far more considerate of the next person to look at that code, even if it's the code's author more than a few months from when it was written!
BulldogLowell:
@zhomeslice,That's a good example of how a Lambda can be put to use.
Attaching them to some array of function pointers where the respective anonymous functions are defined in yet Amo ther unattached and un-referenced function (i.e. your other example) would at best be an academic exercise but in use... well... not particularly useful at all.
Defining the respective functions, naming them with useful monikers, and assembling them into a usefully named array is by far more considerate of the next person to look at that code, even if it's the code's author more than a few months from when it was written!
So to make it easier to read you would recommend doing something like this?
#define interruptPin 2
volatile int Counts = 400; // count per revolution
volatile unsigned long timeX = 1;
volatile unsigned long LastTime;
volatile int PulseCtrX;
unsigned long MicroS_in_Onr_Minute = 60000000;
void TachometerInterruptSetup(){
attachInterrupt(digitalPinToInterrupt(interruptPin), []() {
static int Ctr;
unsigned long Time;
Ctr++;
if (Ctr >= Counts) { // decrease the number pulses used.
Time = micros();
timeX += (Time - LastTime); // this time is accumulative ovrer those "Counts" readings
LastTime = Time;
PulseCtrX ++; // will usually be 1 unless something else delays the sample
Ctr = 0;
}
}, FALLING);
}
void setup() {
Serial.begin(115200);
TachometerInterruptSetup();
}
void loop() {
// Other code to handle tachometer input
if (PulseCtrX) {
static unsigned long SpamTimer;
if ((millis() - SpamTimer) >= (100)) {
SpamTimer = millis();
Serial.print(MicroS_in_Onr_Minute / timeX);
Serial.println("RPM");
}
PulseCtrX = 0;
}
}
or would this be more appropriate (No Lambda)?
#define interruptPin 2
volatile int Counts = 400; // count per revolution
volatile unsigned long timeX = 1;
volatile unsigned long LastTime;
volatile int PulseCtrX;
unsigned long MicroS_in_Onr_Minute = 60000000;
void TachometerInterruptSetup(){
static int Ctr;
unsigned long Time;
Ctr++;
if (Ctr >= Counts) { // decrease the number pulses used.
Time = micros();
timeX += (Time - LastTime); // this time is accumulative ovrer those "Counts" readings
LastTime = Time;
PulseCtrX ++; // will usually be 1 unless something else delays the sample
Ctr = 0;
}
}
void setup() {
Serial.begin(115200);
// attach interrupt to encoder with 400 pulses per revolution
attachInterrupt(digitalPinToInterrupt(interruptPin), TachometerInterruptSetup, FALLING);
}
void loop() {
// Other code to handle tachometer input
if (PulseCtrX) {
static unsigned long SpamTimer;
if ((millis() - SpamTimer) >= (100)) {
SpamTimer = millis();
Serial.print(MicroS_in_Onr_Minute / timeX);
Serial.println("RPM");
}
PulseCtrX = 0;
}
}
Thanks in advanced for the advice ![]()
Z
BulldogLowell:
Attaching them to some array of function pointers where the respective anonymous functions are defined in yet Amo ther unattached and un-referenced function (i.e. your other example) would at best be an academic exercise but in use... well... not particularly useful at all.
I understand your concern with function in an array but have you looked at attachInterrupt() source code? Arduino does this very thing!
WInterrupts.c
attachInterrupt() code simplified a little ![]()
// located in wiring_private.h
typedef void (*voidFuncPtr)(void);
// located in WInterrupts.c
static void nothing(void) {
}
// simplified I removed the #if ... #endif
static volatile voidFuncPtr intFunc[] = {
nothing,
nothing,
nothing,
nothing,
nothing,
nothing,
nothing,
nothing,
nothing,
};
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
intFunc[interruptNum] = userFunc; // <<<<<<<<<<<<<<<<<< function stored in a function pointer array!
// Configure the interrupt mode (trigger on low input, any change, rising
// edge, or falling edge). The mode constants were chosen to correspond
// to the configuration bits in the hardware register, so we simply shift
// the mode into place.
// Enable the interrupt.
//... other code ...
}
#define IMPLEMENT_ISR(vect, interrupt) \
ISR(vect) { \
intFunc[interrupt](); \
}
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
And so each time we use attachInterrupt() we use pointers to arrays of functions that we populate with our custom function or im my case Lambda functions. ![]()
Z
TachometerInterruptSetup
How about just:
handleTachometerInterupt()
Why all the cloak and dagger?
Naming a function with some indication of what it does is a very nice thing.
A Lambda is generally used (as in your nice attachInterrupt() example, as an inline tool where you want to whip up a function that likely won't be used anywhere else. The minute you saw utility outside that one event, you'd likely convert it to a function. You would not want to be calling a Lambda defined in some other function which has to be called by hunting down the pointer that points to some anonymous 'function!'
A proper function is referenced by its name and has utility across your program (i.e. Can be called from any function) or is even portable across programs (make a library or a collection of helper functions).
I guess what I am trying to say is that unless forced by gunpoint, most experienced programmers wouldn't agree that there is any intrinsic benefit to your original example over simply defining aptly-named functions and if convenient, putting them together by creating an array of pointers to those functions... just like the Arduino IDE example you posted. Rather they may feel that it serves only to obfuscate the engine under the hood... a net negative.
BulldogLowell:
TachometerInterruptSetupHow about just:
handleTachometerInterupt()Why all the cloak and dagger?
Naming a function with some indication of what it does is a very nice thing.
A Lambda is generally used (as in your nice attachInterrupt() example, as an inline tool where you want to whip up a function that likely won't be used anywhere else. The minute you saw utility outside that one event, you'd likely convert it to a function. You would not want to be calling a Lambda defined in some other function which has to be called by hunting down the pointer that points to some anonymous 'function!'
A proper function is referenced by its name and has utility across your program (i.e. Can be called from any function) or is even portable across programs (make a library or a collection of helper functions).
I guess what I am trying to say is that unless forced by gunpoint, most experienced programmers wouldn't agree that there is any intrinsic benefit to your original example over simply defining aptly-named functions and if convenient, putting them together by creating an array of pointers to those functions... just like the Arduino IDE example you posted. Rather they may feel that it serves only to obfuscate the engine under the hood... a net negative.
So with no intent of Cloak and Dagger ![]()
What would be the absolute best way to handle this scenario, by the way OP has the question about arrays and function pointers, I'm interested in proper coding techniques related to lambda?
We are in agreement with how arduino created the array of function pointer and handled each relating to the associated pin interrupt.
A) the traditional way documented in arduino:
void MyFunction(){
// Do something
}
void setup(){
attachInterrupt(0, MyFunction, FALLING);
}
B) using Lambda in a separate function(my Favorite):
void MyInterruptSetupFunction(){
attachInterrupt(0, [](){
// Do something
}, FALLING);
}
void setup(){
MyInterruptSetupFunction();
}
C) Separate Functions
void MyFunction(){
// Do something
}
void MyInterruptSetupFunction(){
attachInterrupt(0, MyFunction , FALLING);
}
void setup(){
MyInterruptSetupFunction();
}
D) lambda with no separate function
void setup(){
attachInterrupt(0, [](){
// Do something
}, FALLING);
}
Your opinion matters and I hope to understand proper coding. I use javascript and jquery in my web development and it uses lots of callbacks and such onClick onMouseover etc. I am familiar with this technique but I am self taught
I sometimes feel when I'm programming for my arduino I'm in the dark ages... Can't use lambda its to confusing lol ![]()
Z
I hope to understand proper coding.
I don't see anything wrong with using lamba as in your examples B and D, but I don't see any big advantages, either. Seems like it would be somewhat harder to debug (no separate function name context for the ISR code), and sort of "gratuitously incompatible" with plain C.
And I still don't see what the OP wanted to accomplish with an array of lambdas... (Hmm. Can you combine lambdas and ordinary function pointers in an array? That might be interesting...)
Considering how complex arrays of functions are to declare
Meh. Insufficient use of typedef:
typedef bool (*pkt_callback)(paktype *);
pkt_callback process_packet[] = {bad_packet, // HOPOPT
icmp_packet, // ICMP
bad_packet, // IGMP
bad_packet, // GGP
ipInIp_packet, // 4
bad_packet, // Internet Stream
tcp_packet };
As I mention here you can make an array of lambda functions.
// array of function pointers
void (*doActionsArray []) () =
{
[] { Serial.println (0); } ,
[] { Serial.println (1); } ,
[] { Serial.println (2); } ,
[] { Serial.println (3); } ,
[] { Serial.println (4); } ,
};
void setup ()
{
Serial.begin (115200);
Serial.println ();
int action = 3; // 3 is an example
doActionsArray [action] ();
} // end of setup
void loop () { }