Pages: [1]   Go Down
Author Topic: Using .h and .cpp files in same directory as sketch  (Read 453 times)
0 Members and 1 Guest are viewing this topic.
New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 516
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to figure out how to use .cpp and .h files in the same directory as my sketch, but I'm getting compile errors.  I created a simple sketch with 3 files all in the same folder: Include_Lib_Test.ino, MyLib.h & MyLib.cpp.  They use a button library, Button.h which is in my libraries folder

Here's the code for the 3 files

Code:
// Include_Lib_Test.ino
#include "MyLib.h"
#include <Button.h>
void setup() { }
void loop() {
  readbutton();
}

Code:
// MyLib.h
#ifndef _MYLIB_H
#define _MYLIB_H
#include <Button.h>
Button helloButton = Button(2, LOW);
void readbutton();
#endif

Code:
// MyLib.cpp
#include "MyLib.h"
void readbutton() {
  helloButton.listen();
}

I get this compile error:

MyLib.cpp.o: In function `__static_initialization_and_destruction_0':
MyLib.h:5: multiple definition of `helloButton'
Include_Lib_Test.cpp.o:/Applications/Include_Lib_Test.ino:4: first defined here

I attached Button.h and .cpp for reference

* Button.h (2.91 KB - downloaded 7 times.)
* Button.cpp (10.22 KB - downloaded 8 times.)
Logged

Offline Offline
Edison Member
*
Karma: 58
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The Arduino software scans the files for function prototyping and include files before compiling.
There is an error with that, it doesn't look at the "#ifndef", so you end up declaring "hello button" twice.

Could you try to remove the includes from all files.
Use only this in the *.ino file:
Code:
#include <Button.h>
#include "MyLib.h"

If you get an error, perhaps you have to include one more in a file.

You probably don't need to do the prototyping in the *.h file. But it's okay, so you don't have to remove it.

Please declare the helloButton in the *.ino file.
Creating a class in a *.h file could easily cause problems, I try to avoid that.

If you are making a libary, you have to include specifically what is used.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The Arduino software scans the files for function prototyping and include files before compiling.
There is an error with that, it doesn't look at the "#ifndef", so you end up declaring "hello button" twice.
Not exactly. What happens is that the .ino file is converted to a .cpp file, and compiled. That compilation unit references the header file, so an instance of the Button class is created.

Then, the source file is compiled. It references the header file, so another instance of the Button class is created.

Then, the two compilation units are linked, and there are two instances of the Button class.

Your solution is correct, though the reason for the correction being needed is wrong. Creating is the wrong word to use. Defining a class in a header file is necessary. Instancing it in a header file is not good.
Logged

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 516
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the clarification.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 222
Posts: 12520
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Variables should be defined in .cpp files. The definition means, in effect: allocate some memory to hold a Button, name it helloButton and initialise it to this value ...
Code:
Button helloButton = Button(2, LOW);

If you need to access a variable from other files, you should add an external declaration in a header file and include that wherever you need to access it. The external declaration means, in effect: the symbol helloButton refers to a Button which is defined in some other file ...
Code:
extern Button helloButton;

In this case you don't refer to helloButton from outside MyLib.cpp so you don't actually need the external declaration.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 516
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Variables should be defined in .cpp files. The definition means, in effect: allocate some memory to hold a Button, name it helloButton and initialise it to this value ...
Code:
Button helloButton = Button(2, LOW);

If you need to access a variable from other files, you should add an external declaration in a header file and include that wherever you need to access it. The external declaration means, in effect: the symbol helloButton refers to a Button which is defined in some other file ...
Code:
extern Button helloButton;

In this case you don't refer to helloButton from outside MyLib.cpp so you don't actually need the external declaration.


That's a big help.  Because I moved
Code:
Button helloButton = Button(2, LOW);
to the .ino file per the previous suggestion.  But I got this compile error:
MyLip.cpp: In function 'void readbutton()':
MyLip.cpp:5: error: 'helloButton' was not declared in this scope

So if I add to MyLip.cpp this:
Code:
extern Button helloButton;
Then it compiles fine.
Logged

Pages: [1]   Go Up
Jump to: