EDIT: The code marked as “not working” was actually working. It was because of a syntax problems in my tests, not detected by the compiler. So the question is already solved, thank you.
C++ is not a language I use everyday, so it is possible that the solution is trivial.
About the context first. I use C++ to develop on a microcontroller (Arduino-based, AVR microcontroller), so I do not use the STL, printf-like functions, new/malloc should be avoided and C++ <string> too.
I have an object called Serial similar to the C++ cout iostream, to communicate with the microcontroller with a serial interface. I have overloaded the “<<” operator of the class from which Serial is an instance so I can do something like that:
Serial << "debug " << "value is " << 3 << endl;
// Whithout the << operator it would be:
Serial.print("debug ");
Serial.print("value is ");
Serial.println(3);
I would like to create a function (or a macro) that enables this kind of line only if debugging is enabled, and which automatically add the “debug” string and append the “endl” value at the end.
So something like that (warning, code does not work because “data” cannot expand as a whole C++ instruction):
#ifdef DEBUG
#define PRINT_DEBUG(data) do {Serial << "debug " << data << endl;} while(0)
#else
#define PRINT_DEBUG(data) do {} while(0)
#endif
// This code works
PRINT_DEBUG("hello world");
// This code does not work
int value1 = 3;
char * value2 = "this is a string";
PRINT_DEBUG("sensor1 value:" << value1 << " other sensor value " << value2);
This kind of function/macro would allow me to easily output strings on my serial interface with a specific “string protocol” without having to repeat the “debug” string at the start. It would also allow me to easily disable the print of debug message by not setting the DEBUG macro. I also have only one “#ifdef DEBUG” instead of several ones in my code.
I managed to do something like that with variadic arguments, but I hate this solution because it is dangerous to use (I do not want to specify the number of arguments), and I cannot mix different type of data:
void __rawSend(char * args, ...) {
Serial.print(args);
va_list paramList;
va_start (paramList, args);
while(true) {
char * next = va_arg(paramList, char*);
if (next == NULL) {
break;
}
Serial.print(" ");
Serial.print(next);
}
Serial.println();
va_end(paramList);
}
#ifdef DEBUG
#define printDebug(...) do {__rawSend(OUTPUT_DEBUG, __VA_ARGS__, NULL);} while(0)
#else
#define printDebug(...) do {} while(0)
#endif
int intValue = 1;
char * stringValue = "data";
// This works
printDebug("hello",stringValue);
// This does not works
printDebug("data is", intValue);
How can I do that? Is it possible with macros (while avoiding variadic arguments and mixing different kind of types)? Is there a better solution?
Sorry all, the code marked as “not working” does actually work. It was because of a syntax problems in my tests, not detected by the compiler.
Anyway, my solution can benefit other people working with Arduino, as I have seen solutions using printf or trying to recreate printf.
I used the “<<” operator coming from http://arduiniana.org/libraries/streaming/