Is there a way to define a macro in a header file using a class structure such that it would be a simple matter of calling the name of the class along with the macro to affect change on that global variable?
Here is a simplified example of what I'm trying to do ... but obviously this doesn't work:
#ifndef Library_h
#define Library_h
bool itemEnabled;
class Library {
#define DISABLE_ITEM itemEnabled = false
public:
Library(unsigned long time, char color);
private:
unsigned long timeValue = 0;
char mainColor;
};
#endif
And I'd like to be able to call the macro in a sketch like this - or in some similar simple fassion:
A variable can only be modified in functions, do that in setup for example (and if it’s defined as a global in another file, it needs to be declared extern so that the main sketch would know about it)
So that's kind of why I wanted to be able to set it with a macro ... in terms of simplicity for the user of the library ... instead of having them do this:
itemEnabled = false;
Which has no reference to this library, I would much prefer to have them do this:
Library::DISABLE_ITEM
or some similar way where the library is referenced and they know that they are affecting change on a variable that is specific to Library.
You can only give a default value to a variable where you allocate the memory (define the variable). So if later you want to change that value then this is code that has to be executed and thus it needs to be in a function.
You could write ClassName::variable = false; if you want (for a public static attribute) or call a method on your library that will modify the variable.
The fewer preprocessor macros you use the better. Make itemEnabled a private member of your library class and supply a public setter function. Also, if the user ever needs to know the variable's value, provide a public getter function.
In the context of a class, the rough equivalent of a 'global variable' is a 'class static variable'. It's a variable shared with all instances of the class. A 'class static function' can be used to modify the 'class static variable'.
Note: If your library has a .cpp file as well as the .h file you should put the definition of the class static variable there: bool Library::itemEnabled = true;
If that line is in the .h file you can't use the .h file in more than one .cpp/.ino file or you'll get multiple definitions of 'itemEnabled'.
But why would you do this?
It is immediately clear that Library::disable(); is a function call that disables something in Library. DISABLE_ITEM; on the other hand is not a standard C++ statement or expression, it is impossible to tell what it is or what it's doing without diving into the library source code to look at its definition.
first, this is clear, because you can't assign a new value outside setup() or loop
this compiles:
#include "library.h"
//itemEnabled = false; // the variable can not get a new value here
void setup() {
itemEnabled = false; // the variable can be set here
}
void loop() {
itemEnabled = false; // the variable can be set here
}
if you have global variable in your .h and you want to let the user modify the variable, you could introduce simple functions for that like a
"switchOn()" and "switchOff()
A makro would be my last option in 2021.
But does it really need to be a global?
as johnwasser and J-M-L already mentioned, if you want the context to your class, why not a static member within your class and call a method with any object of that class?
btw: as you mentioned you want to write a library (for others): I highly recommend this article Sparkfun: How to Write a Great Arduino Library
first they inlcude 2 important links to Arduino articles you should read, and then they share their expirience of how to write a library with do's and don'ts
And this is EXACTLY the situation I am in. I need the variable to be viewable in whatever value it has assigned to it - to all instances of the class. However, the library is indeed composed of a header file and a .cpp code file.
So what do I do in my situation where I need the variable to exist outside of any instantiations of the library class, but also modifiable by the user's code? What this is ... it's a simple non-blocking timer library that has a feature where it keeps an array of the class every time it is instantiated so that the user can issue a single reset command and reset all instantiated timers at once. But I want to be able to offer the ability to disable that feature in the interest of saving memory if someone is in that situation where every byte counts.
The library has been written and published for some time now. This post was over something I've been trying to implement into the library. Specifically, the ability to disable a function that exists outside of the class definitions.
I was able to do what I wanted to do finally, by using an enum that is declared outside of the class structure and the using a variable inside the class, and then use Maco's that get passed into any of the class definitions.
If you want any code to be able to modify the variable at any time, move it to the public: part of the class declaration. Then any code that knows the name can change the value. The macro can then be:
I prefer to keep a class's internal state variables private. Then, supply public setter and getter functions. That way I control what the user is allowed to do.
As pointed out in this post and OP's other similar post, using preprocessor macros should be avoided if there's a better solution. In this case there is.