What is the correct default value to give a function pointer when the function pointer parameter is an optional parameter in a library function ?
Currently I have
void update(callbackFunc func = nullptr);
callbackFunc has previously been defined like this, but I am not sure that int is the right data type
typedef void (*callbackFunc) (int arg1); //is int right ?
The library function tests for the value in the function like this
if (func == nullptr)
{
_callbackRequired = false;
}
It works, but is it correct ?
Full code below
TestCallback.cpp
#include "Arduino.h"
#include "TestCallback.h"
TestCallback::TestCallback()
{
_callbackRequired = false;
}
void TestCallback::begin()
{
_startCount = 5;
_currentCount = 5;
_period = 500;
}
void TestCallback::update(callbackFunc func = nullptr)
{
if (func == nullptr)
{
_callbackRequired = false;
}
else
{
cb1 = func;
_callbackRequired = true;
}
_currentTime = millis();
if (_currentTime - _startTime >= _period)
{
_previousCount = _currentCount;
_currentCount--;
if (_currentCount < 0)
{
_currentCount = _startCount;
}
_startTime = _currentTime;
if (_callbackRequired)
{
cb1(_currentCount); //execute the callback function
}
}
}
TestCallback.h
#ifndef TestCallback_X
#define TestCallback_X
#include "Arduino.h"
class TestCallback
{
private:
int _startCount;
int _currentCount;
int _previousCount;
unsigned long _currentTime;
unsigned long _startTime;
unsigned long _period;
boolean _callbackRequired = true;
int _number = 123;
public:
TestCallback();
typedef void (*callbackFunc) (int arg1); //create function pointer type
callbackFunc cb1; //an instance of the function pointer type
void begin();
void update(callbackFunc func = nullptr);
};
#endif
TestCallback.ino
#include "TestCallback.h"
TestCallback testing;
void setup()
{
Serial.begin(115200);
testing.begin();
}
void loop()
{
testing.update(printCount);
}
void printCount(int count)
{
Serial.println(count);
}
typedef void (*callbackFunc) (int arg1); //is int right ?
for typing a function signature you can just use:
typedef void (*callbackFunc) (int);
but prefer to use your C++, because you do not need to create a new type, it already exists:
using callbackFunc = void (*)(int);
uninitialized class member pointers will be nullptr by default, but I like that you explicitly initialize it.
you don't need all this:
void TestCallback::update(callbackFunc func = nullptr)
{
if (func == nullptr)
{
_callbackRequired = false;
}
else
{
cb1 = func;
_callbackRequired = true;
}
pointers can be truth tested:
if (func) {
cb1 = func;
}
likewise when you call it... not like this:
if (_callbackRequired)
{
cb1(_currentCount); //execute the callback function
}
but this:
if (cb1)
{
cb1(_currentCount); //execute the callback function
}
so you save a variable, _callbackRequired isn't necessary.
Thanks for the feedback. I'm off to experiment
Changes made and it still works !
Unless anyone is really interested I won't post the revised code but if anyone would like to see it I will gladly post it.
UKHeliBob:
Changes made and it still works !
Unless anyone is really interested I won’t post the revised code but if anyone would like to see it I will gladly post it.
One more thing… since you are using a function pointer: If your function is only called from one place, you don’t need to create a whole separate function, you can use a lambda with the same signature:
class TestCallback
{
private:
int _startCount;
int _currentCount;
int _previousCount;
unsigned long _currentTime;
unsigned long _startTime;
unsigned long _period;
int _number = 123;
public:
TestCallback();
using callbackFunc = void (*) (int);
callbackFunc cb1;
void begin();
void update(callbackFunc func = nullptr);
};
TestCallback::TestCallback()
{
}
void TestCallback::begin()
{
_startCount = 5;
_currentCount = 5;
_period = 500;
}
void TestCallback::update(callbackFunc func)
{
cb1 = func;
_currentTime = millis();
if (_currentTime - _startTime >= _period)
{
_previousCount = _currentCount;
_currentCount--;
if (_currentCount < 0)
{
_currentCount = _startCount;
}
_startTime = _currentTime;
if (cb1)
{
cb1(_currentCount); //execute the callback function
}
}
}
TestCallback testing;
void setup() {
Serial.begin(9600);
testing.begin();
}
void loop() {
testing.update([](int count){
Serial.println(count);
});
}
//or even like this:
//void loop() {
// auto printCount = [](int count) {
// Serial.println(count);
// };
//
// testing.update(printCount);
//}
//or even more pedantic, like this:
//void loop() {
// TestCallback::callbackFunc printCount = [](int count) {
// Serial.println(count);
// };
//
// testing.update(printCount);
//}
you can use a lambda with the same signature:
I think that I will pass on that suggestion for now, at least until I have got a callback implemented in my larger library.