Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arduino library: multiple definitions of a function

Tags:

c++

arduino

Today I encountered a weird problem when trying to use IRremote library, and I managed to strip down the problem as following. If you have a folder in libraries, with Foo.h and Foo.cpp inside, and write a sketch to include Foo.h:

Foo.h

#ifndef Foo_H
#define Foo_H

int AAA() {
    return 0;
}

#endif

Foo.cpp

#include "Foo.h"

Sketch

#include <Foo.h>

void setup(){

}

void loop(){

}

The error message is:

 Foo\Foo.cpp.o: In function `AAA()':

 E:\workShop\Arduino\libraries\Foo\/Foo.h:5: multiple definition of `AAA()'

 includeTest.cpp.o:E:\workShop\Arduino\libraries\Foo/Foo.h:5:

 first defined here

I'm using a Windows 7 32-bit machine. Tested on Arduino 1.0.5, 1.0.4, and 21, 22.


So with some research I figured out the problem comes from my confusion of preprocessor and linking. This question explains how preprocessor includes file and include guard:

  • In C++ why have header files and cpp files?

These are some of the pages helped me understand linking:

  • 1.8 — Programs with multiple files

  • GCC and Make - A Tutorial on how to compile, link and build C/C++ applications

  • Guide: Multiple sources

And this is a better explanation of inline specifier:

  • inline specifier
like image 908
Xun Yang Avatar asked Jun 14 '13 11:06

Xun Yang


3 Answers

Well, you have defined the function in two places: once in Foo.cpp where it includes the header, and again in your sketch where it includes the header. C and C++ headers don't provide a module system, they're just literally pasted in place of the include statement.

Either declare AAA in the header, but define it in Foo.cpp (so there's only one definition), or mark it inline.

like image 53
Useless Avatar answered Oct 29 '22 07:10

Useless


Well, the distribution of stuff in your files is more than unusual to say the least.

Here is how it is commonly done:

Foo.h

#ifndef Foo_H
#define Foo_H

int AAA(void);  // Just the prototype, not the function body

#endif

Foo.cpp

#include "Foo.h"   // include the h file, although not strictly neecessary

// make the function and body
int AAA(void)
{
    return 0; 
}

Sketch.cpp

#include <Foo.h>  // include prototype, so the AAA function becomes known

void setup()
{
     ...
     AAA();   // call AAA somewhere
}

void loop(){

}
like image 36
Bbrado Avatar answered Oct 29 '22 08:10

Bbrado


You define the function in the header, so you should use the inline keyword:

inline int AAA(){return 0;}
//               ^^^^^^^^^^ definition

Alternatively, place only the declaration in the header, and the definition in an implementation .cpp file, to be compiled.

Foo.h

#ifndef Foo_H
#define Foo_H

int AAA();

#endif

Foo.cpp

#include "Foo.h"

int AAA(){return 0;}
like image 31
juanchopanza Avatar answered Oct 29 '22 07:10

juanchopanza