I am trying to make my own library and it uses some local variables with the same name as some variables in ino. Compiler complains about it. I stripped it to (nonsence but simple) example
mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
int doit();
#endif
mylib.cpp:
#include "mylib.h"
int value;
int doit(){
return value++;
}
example.ino:
#include "mylib.h"
int value;
void setup(){
value=3;
pinMode(13,OUTPUT);
}
void loop() {
digitalWrite(13,(value==doit()) );
}
compiling:
$ make
/usr/bin/avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p example.o mylib.o .lib/arduino.a -lm -o example.elf
mylib.o:(.bss.value+0x0): multiple definition of `value'
example.o:(.bss.value+0x0): first defined here
collect2: error: ld returned 1 exit status
/home/gilhad/GIT/HW/Arduino/minipro//../Arduino.mk:436: recipe for target 'example.elf' failed
make: *** [example.elf] Error 1
I am not usint the value
in the .h
file, so why it collides with similary named variable from another module?
Should not be it private to the module until exposed via .h
file?
2 Answers 2
I am not usint the value in the .h file, so why it collides with similary named variable from another module?
Should not be it private to the module until exposed via .h file?
The quick answer is that a source code file is not a separate unit. The last step in the build process is to link all the object file and create the executable binary. The linker will need to resolve all the symbols. In this case there are two definitions and the compiler cannot resolve the references. The linker can be told to ignore multiple definitions.
The keyword "static" will make the symbol local to the compiled unit (object file). As the keyword "external" tells the compiler that the definition is in another compiled unit. Header files is just a structuring convention. The language does not actually say anything about this. It is a pre-processor (cpp) in the build process that creates the combined source code for the compiler.
C++ (and OOP) adds a number of ways to control the visibility of symbols (aka encapsulation). In a class definition the keywords "public", "protected" and "private" may be used. Also the keyword "static" may be used. In this case it means that the symbol is defined globally for the class (class variable) and not per instance (member variable).
The keyword "static" in C/C++ is actually a "recent" development of the languages. In the early versions of C local symbols where prefixed with underscore "_local". This is still a common practice even though the object files contain much more scope information today.
Cheers!
The common practice is to write Arduino libraries using C++ classes:
The core of the header file consists of a line for each function in the library, wrapped up in a class along with any variables you need.
class Morse
{
public:
Morse(int pin);
void dot();
void dash();
private:
int _pin;
};
In this way you can specify what is private (variables and methods only seen within the class) and what is public (variables and methods that can be seen outside the class). In the given example, the variable called "_pin" is private to the class Morse.
In your case, you would want to make a private class variable called "value". Because it is private, you are free to re-use the name when not inside the class.
I
do not know something, which I should know. And I am planning to write much complicated projects, so I want to know not only how make things nice, but also how it works under hooks when I want to poke really deep :)