Arduino库:一个函数的多个定义

Arduino library: multiple definitions of a function

本文关键字:函数 定义 一个 Arduino      更新时间:2023-10-16

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

foo。

#ifndef Foo_H
#define Foo_H
int AAA() {
    return 0;
}
#endif

Foo.cpp

#include "Foo.h"

草图
#include <Foo.h>
void setup(){
}
void loop(){
}

错误信息是:

 FooFoo.cpp.o: In function `AAA()':
 E:workShopArduinolibrariesFoo/Foo.h:5: multiple definition of `AAA()'
 includeTest.cpp.o:E:workShopArduinolibrariesFoo/Foo.h:5:
 first defined here

我用的是Windows 7 32位的电脑。在Arduino 1.0.5, 1.0.4和21,22上测试。


所以经过一些研究,我发现这个问题来自于我对预处理器和链接的混淆。这个问题解释了预处理器如何包含file和include guard:

  • 在c++中为什么有头文件和cpp文件?

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

  • 1.8 -程序与多个文件

  • GCC and Make -如何编译、链接和构建C/c++应用程序的教程

  • 指南:多个源

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

  • 内联说明符

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

要么声明 AAA在头,但定义它在Foo.cpp(所以只有一个定义),或标记为inline

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

通常是这样做的:

foo。

#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(){
}

在header中定义函数,因此应该使用inline关键字:

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

或者,只将声明放在头文件中,将定义放在要编译的.cpp实现文件中。

foo。

#ifndef Foo_H
#define Foo_H
int AAA();
#endif

Foo.cpp

#include "Foo.h"
int AAA(){return 0;}

如果您的程序结构稍微复杂一些,那么它比brado的答案要复杂一些。您需要#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