How to call function and retrieve two returns in Arduino or C? - Stack Overflow
SOLVED! Need guidance - how to return multiple values from one function.
Returning multiple values from a method
Returning more than one value from a function.
Videos
You can't return two times at once.
You could pass b to your function by reference.
yourfunction( long a , long* b )
{
*b = a + 10;
//more code
return a;
}
a = yourfunction(a , &b );
You can't return more than one value from a function in C. Either return a struct, or pass by reference and modify in the function.
Example 1: struct
struct ab {
long a;
long b;
}
struct ab Conv(double num) {
struct ab ab_instance;
ab_instance.a = floor(num);
ab_instance.b = num * pow(10,6) - a * pow(10,6);
return ab_instance;
}
Example 2: pass b by reference
long Conv(double num, long& b) {
long a;
a = floor(num);
b = num * pow(10,6) - a * pow(10,6);
return a;
}
It looks to me like you are trying to find the right answer to the wrong
question, typical of an XY problem. In the example you provide in
your own answer, you call the function pointer right after having set
its value. In this case, there is no use to the function pointer, as you
could directly call either read_chars() or write_chars().
Obviously, this is just because that example is excessively simplified. In a more realistic use case, you would set the function pointer in one part of the code, and call it in a completely different part. Assuming the functions and the pointer are defined like this:
void (*fun_ptr)();
void read_chars(uint8_t address) {
printf("address of array is 0x%.2x\n", address);
}
void write_chars(uint8_t row, uint8_t col, const char *str) {
printf("[%d, %d]: %s\n", row, col, str);
}
One section of the program sets the pointer:
// Here we learn what action should be performed.
if (should_read()) {
fun_ptr = (void(*)()) read_chars;
} else { // should write
fun_ptr = (void(*)()) write_chars;
}
and a different section calls it:
// Here we have to perform the action.
if (fun_ptr == (void(*)()) read_chars) {
((void(*)(uint8_t)) fun_ptr)(1);
} else if (fun_ptr == (void(*)()) write_chars) {
((void(*)(uint8_t, uint8_t, const char *)) fun_ptr)(
1, 1, "messaage0");
}
Note that this second section must know what function it is calling
in order to pass the correct arguments. Hence the if...then test. Note
also that, in order to have valid C++, you must explicitly cast the
function pointer before calling it. This gets very clumsy, and it is a
lot more convenient to store this information (what function should be
called) in an enum rather than a function pointer:
enum {
CALL_NONE, CALL_READ_CHARS, CALL_WRITE_CHARS
} what_to_call = CALL_NONE;
which would be used like this:
// Here we learn what action should be performed.
if (should_read()) {
what_to_call = CALL_READ_CHARS;
} else {
what_to_call = CALL_WRITE_CHARS;
}
// ...
// Here we have to perform the action.
if (what_to_call == CALL_READ_CHARS)
read_chars(1);
else if (what_to_call == CALL_WRITE_CHARS)
write_chars(1, 1, "messaage1");
That being said, it is often the case that when it is time to perform
the action, the part of the code responsible of doing so does not know
what arguments should be passed, and this information is more readily
available at the time when when learn what action should be performed.
This is a quite common situation, and a standard C idiom in this case is
to give the function a void * parameter that it will cast to the
appropriate type in order to retrieve the data it needs. For instance:
void (*fun_ptr)(void *);
void *fun_ptr_data;
void read_chars(void * data) {
uint8_t address = * (uint8_t *) data;
printf("address of array is 0x%.2x\n", address);
}
struct write_chars_data {
uint8_t row;
uint8_t col;
const char *str;
};
void write_chars(void *data) {
write_chars_data *d = (write_chars_data *) data;
printf("[%d, %d]: %s\n", d->row, d->col, d->str);
}
Note that, since write_chars() needs to retrieve multiple parameters
from a single pointer, it uses a pointer to a struct.
Now, the part of the code that learns what should be done has the responsibility of providing the data:
// Here we learn what action should be performed.
if (should_read()) {
fun_ptr = read_chars;
uint8_t *p = new uint8_t;
*p = 1;
fun_ptr_data = (void *) p;
} else { // should write
fun_ptr = write_chars;
write_chars_data *p = new write_chars_data;
p->row = 1;
p->col = 1;
p->str = "messaage2";
fun_ptr_data = (void *) p;
}
The part of the code that has to perform the action now is very simple:
// Here we have to perform the action.
if (fun_ptr)
fun_ptr(fun_ptr_data);
Note that this code snippet doesn't free the allocated memory. You will have to figure out who will be responsible for that.
This pattern is quite common in libraries, where the client (the user of
the library) wants an action to be performed, but the library is
responsible for performing that action at the right time. The client
would then provide the library a pointer to a function that accomplishes
the action (called a “callback”), together with a generic pointer to the
data needed by the callback. The use of a generic void * pointer makes
sense, because the library cannot know what kind of data the callback
will need.
In your case, since you know what kind of data you may need, you could
use a pointer to an union instead of a generic pointer:
union fun_data {
uint8_t address; // for read_chars
struct { // for write_chars
uint8_t row;
uint8_t col;
const char *str;
};
};
void (*fun_ptr)(fun_data *);
fun_data *fun_ptr_data;
A more idiomatic C++ style would be to pack together the callback function and its data into a “functor”, i.e. an object that can be called like a function, and can also store the data it needs. You would then use inheritance in order to create specific functor types while calling a generic one.
I assume, that the fun_ptr points to the different service functions to do some kind of animation other other long running tasks on your display, thus you want to repeatedly call them in a structured way.
What you are currently doing will not really work. When you call a function, you need to provide its arguments. That's the same for a function pointer. You cannot call a function, that demands parameters, without any parameters. While you can still set a function pointer of type (void (*)(void*) to a function of type (void (*)(uint8_t)), the compiler warns so, because you still cannot call the function without any parameter. If you are trying to do so, you will still get an error of too few arguments to function ....
I see 2 ways to go from here:
You could overload your functions, so that a version without any parameters exists. Like this:
void foo(uint8_t i){Serial.println(i);} void foo(){foo(10);}With 10 being the value, with which the function should be called, when you provide no parameters. You can of course also use variables or function calls here, to actually get that value for the parameter
i. Then you can use the pointer to call that function:void (* p)(void); p = &foo; p();The assignment of the pointer will choose the version of the function without any parameters out of the overloaded pool of this function, since that matches the type of the pointer. Note, that I removed the
*from thevoidparameter definition. I don't understand, what that would mean anyway (pointer to void?). The function pointerp()can now be called without any parameters, since it points to a function without any parameters.You could ditch the function pointer and use a simple switch case statement with a state variable (which holds some identifier for the corresponding function), to call the correct service function. I won't go into detail here, since that is already basically, how an FSM can be programmed in C++, which is covered on this site and on the web numerous times.
If I were you, I probably would go with the first option, though that might also depend on the overall logic, that I currently don't really understand (too few information).
You may create a struct with "x" elements, one for each LED:
struct ArrayOfBooleans {
bool array[4];
};
ArrayOfBooleans myOutputArray;
myOutputArray.array[0] = true;
myOutputArray.array[1] = true;
myOutputArray.array[2] = false;
myOutputArray.array[3] = true;
lightEmUp(myOutputArray);
void lightEmUp(ArrayOfBooleans myOutputArray) {
bool isFirstLightOn = myOutputArray.array[0];
// etc
}
NoTE: If you run into Exception 9 issues (using this logic on another board), please check this answer to another post
Easier than I thought. Found it while reading the docs. Imagine that. :)
To pass in multiple variables, just separate them with a comma.
Docs: https://www.arduino.cc/en/Reference/FunctionDeclaration
Relevant code:
int myMultiplyFunction(int x, int y){
int result;
result = x * y;
return result;
}