8

今天我在尝试使用 IRremote 库时遇到了一个奇怪的问题,我设法将问题排除如下。如果你在库中有一个文件夹,Foo.h里面有一个文件夹Foo.cpp,然后写一个包含 Foo.h的草图:

Foo.h

#ifndef Foo_H
#define Foo_H

int AAA() {
    return 0;
}

#endif

Foo.cpp

#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 上测试。


因此,通过一些研究,我发现问题来自我对预处理器和链接的混淆。这个问题解释了预处理器如何包含文件和包含保护:

这些是帮助我理解链接的一些页面:

这是对内联说明符的更好解释:

4

4 回答 4

13

好吧,您已经在两个地方定义了该函数:一次是在包含标题的 Foo.cpp 中,一次是在包含标题的草图中。C 和 C++ 头文件不提供模块系统,它们只是直接粘贴在包含语句的位置。

要么在标头中声明 AAA,但在 Foo.cpp 中定义它(因此只有一个定义),或者标记它inline

于 2013-06-14T11:50:35.230 回答
6

好吧,至少可以说,文件中内容的分布是不寻常的。

以下是它通常的做法:

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; 
}

草图.cpp

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

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

void loop(){

}
于 2013-06-14T12:00:05.223 回答
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;}
于 2013-06-14T11:51:38.667 回答
0

如果您的程序结构稍微复杂一点,它比 Bbrado 的回答稍微复杂一点。您需要 #include<Arduino.h>和 #include 帮助文件,如下所示:

测试呼叫.ino

#include "testCall.h"
void setup() {
  AAA();
}
void loop() {
}

测试呼叫.cpp

#include "testCall.h"
beeHive AAA(void){
    beeHive a;
    a.bee = (byte)1;
    a.hive = (byte) 2;
    return a;
}

测试呼叫.h

#include <Arduino.h>
struct beeHive {
  byte bee;
  byte hive;
};
beeHive AAA (void); //  prototype only
于 2017-03-09T14:01:17.543 回答