今天我在尝试使用IRremote库时遇到了一个奇怪的问题,我设法将问题删除如下。如果您在库中有一个文件夹,其中包含Foo.h
和Foo.cpp
,并写一个sketch以包含Foo.h:
#ifndef Foo_H
#define Foo_H
int AAA() {
return 0;
}
#endif
#include "Foo.h"
#include <Foo.h>
void setup(){
}
void loop(){
}
错误消息是:
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
我正在使用Windows 7 32位计算机。在Arduino 1.0.5,1.0.4和21,22上测试。
因此,通过一些研究,我发现问题来自于我对预处理器和链接的混淆。这个问题解释了预处理器如何包含文件并包含guard:
以下是帮助我理解链接的一些页面:
这是对内联说明符的更好解释:
答案 0 :(得分:11)
好吧,你已经在两个地方定义了这个函数:一次在Foo.cpp中,它包含标题,再次在你的草图中包含标题。 C和C ++标头不提供模块系统,只是简单地粘贴它们来代替include语句。
在标头中声明 AAA
,但在Foo.cpp中定义(因此只有一个定义),或标记为{{1} }。
答案 1 :(得分:5)
好吧,至少可以说,你文件中的东西分布是不寻常的。
以下是通常的做法:
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(){
}
答案 2 :(得分:1)
您可以在标头中定义该功能,因此您应该使用inline
关键字:
inline int AAA(){return 0;}
// ^^^^^^^^^^ definition
或者,只将标题中的声明和实现.cpp
文件中的定义放在一起进行编译。
foo.h中
#ifndef Foo_H
#define Foo_H
int AAA();
#endif
Foo.cpp中
#include "Foo.h"
int AAA(){return 0;}
答案 3 :(得分:0)
如果你的程序结构稍微复杂一点,它比Bbrado的答案要复杂一点。您需要#include <Arduino.h>
和#include帮助文件,如下所示:
testCall.ino
#include "testCall.h"
void setup() {
AAA();
}
void loop() {
}
testCall.cpp
#include "testCall.h"
beeHive AAA(void){
beeHive a;
a.bee = (byte)1;
a.hive = (byte) 2;
return a;
}
testCall.h
#include <Arduino.h>
struct beeHive {
byte bee;
byte hive;
};
beeHive AAA (void); // prototype only