c++ - 如何将cpp文件添加到arduino项目?

标签 c++ arduino arduino-ide

我正在尝试将一个cpp文件添加到具有以下设置的arduino项目中...

project 
--folder
  --foo.h
  --foo.cpp
--project.ino

我在#include "folder/foo.h的顶部有一个project.ino。但是,尽管 header 提供了函数的原型(prototype),但函数定义在cpp文件中。当我尝试使用Arduino IDE编译代码时,它失败并显示错误Undefined reference to 'bar()'并且bar()位于foo.cpp

我查看了this,但没有sketch/import library的设置(但是我有sketch/include library,但是没有看到任何类似于使用自定义文件夹位置的内容)

我也看了this。但与上述相同,我的想法中不存在该设置。 (我最近下载了哪个)


//project.ino
#include "folder/foo.h"
void setup() {
    Serial.begin(9600);
}
void loop() {
    bar();
}
//folder/foo.h
#include "Arduino.h"
void bar();
//folder/foo.cpp
#include "foo.h"

void bar() {
    Serial.println("bar");
}

错误
/tmp/ccNTRFfU.ltrans0.ltrans.o: In function `loop':
/home/temporary/project/project.ino:9: undefined reference  to `bar()'
collect2: error: ld returned 1 exit status
exit status 1

我希望发生的是一种链接cpp文件夹的方法,而不必将所有文件放在项目的同一根文件夹中。

-编辑1:
添加代码

-编辑2:
添加了#include "Arduino.h"
-编辑3:
添加了Serial.begin(9600);

最佳答案

如何在Arduino项目中正确包含C / C++ header 和源文件。

该答案已经过测试和编译,以确保其有效。 (已在Linux Ubuntu中使用Arduino 1.8.7 IDE完成)。

您有2个问题。

第1个: Arduino的异常生成过程(described here)不允许包含项目目录中该项目的.ino文件所在的子文件夹。

[更新:当我在PC上复制您的代码时,这个错误可能只是我的一个错误,而不是您的错误:我不小心使用了foo.c而不是foo.cpp]
第二个: C++只能在C++源文件中使用,因此您必须将foo.c更改为foo.cpp,因为Serial.println()是C++类(Serial的)println()方法的C++调用。

要修复1 ,只需更改文件夹结构以将所有内容都放在一个文件夹中:

project
├── foo.cpp
├── foo.hh
└── project.ino

我也为下面的#1提供了替代解决方案。

要修复2 ,(这是强制性的!),使foo.c-> foo.cpp和(可选,但建议,以显示为C++头文件)foo.h-> foo.hh。现在也将.ino和.cpp文件中的包含也更新为#include "foo.hh"

而已!现在关闭Arduino IDE,然后重新打开它并重新打开您的项目,您将看到以下新选项卡:

enter image description here

现在可以编译了!

学习:我是怎么知道的?

首先,在Arduino IDE中打开详细编译:文件->首选项->选中“在“编译”期间显示详细输出”框。

现在,当您进行编译时,所有错误将显示在IDE窗口的底部,以及引发该错误的确切编译或链接命令。

一旦我修复了文件夹结构,但是您的文件仍然是C而不是C++文件,我看到了此错误:
Compiling sketch...
/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/tools/avr/bin/avr-gcc -c -g -Os -w -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/arduino/avr/cores/arduino -I/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/arduino/avr/variants/eightanaloginputs /tmp/arduino_build_233569/sketch/foo.c -o /tmp/arduino_build_233569/sketch/foo.c.o
/tmp/arduino_build_233569/sketch/foo.c: In function 'bar':
foo.c:9:5: error: 'Serial' undeclared (first use in this function)
     Serial.println("bar");
     ^
/tmp/arduino_build_233569/sketch/foo.c:9:5: note: each undeclared identifier is reported only once for each function it appears in
exit status 1
'Serial' undeclared (first use in this function)


注意,编译失败的文件是/tmp/arduino_build_233569/sketch/foo.c,并且当时正在使用avr-gcc C编译器(而不是avr-g++ C++编译器)。

然后,我打开/tmp/arduino_build_233569/sketch/foo.c文件进行检查,并查找与之不同的任何东西。

接下来,我使用Eclipse开始跟踪包含,以查看Serial的获取位置(问题出在我面前已经很明显了,但我还没有看到)。我发现以下内容:

Arduino.h可以在“Arduino / Source / Arduino / hardware / arduino / avr / cores / arduino / Arduino.h”中找到。它包括"HardwareSerial.h"。此头externSerial对象:
#if defined(UBRRH) || defined(UBRR0H)
  extern HardwareSerial Serial;
  #define HAVE_HWSERIAL0
#endif

但是,回头看看Arduino.h,您会发现,如果使用C++进行编译,则仅包含HardwareSerial.h:
#ifdef __cplusplus   <========= This means that the following headers are ONLY included if you are compiling with C++! BOOM! That's when it hit me! You're compiling a C file with the C compiler to access a C++ object. That's not ok. Use the C++ compiler!
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
#include "USBAPI.h"
#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL)
#error "Targets with both UART0 and CDC serial not supported"
#endif
#ifdef __cplusplus表示仅当您使用C++编译时,才包含上述 header !就在那时候打我!您正在使用C编译器编译C文件以访问C++对象。那不行您必须改为使用C++编译器。只需将foo.c更改为foo.cpp即可完成此操作。做完了

您的问题1(文件夹结构)的替代修补程序:

从Arduino IDE中找到“素描簿位置”:文件->首选项。例如,我的是/home/gabriel/dev/Arduino/Sketches

现在,去那里并创建一个“libraries”文件夹。对我来说,现在是/home/gabriel/dev/Arduino/Sketches/libraries。现在,该文件夹中的所有内容都被视为Arduino“库”,并且可以包含在内。移动foo.h [在这种情况下,请勿使用foo.hh]和foo.cpp,如下所示:
/home/gabriel/dev/Arduino/Sketches/libraries/foo
├── foo.cpp
└── foo.h     <==== NOT foo.hh in this case!


现在关闭并重新打开Arduino IDE,然后转到Sketch-> Include Library-> foo,它将自动为您添加以下行:
#include <foo.h>

在这种情况下不能使用foo.hh的原因仅是因为Arduino仅在以这种方式使用菜单添加库包括时才在寻找.h文件。 就我而言,这是一个错误,应该向Arduino开发人员报告。 随时接受。

附录:

2019年4月16日:
一个google search for "arduino add include path"使我想到了:https://forum.arduino.cc/index.php?topic=445230.0,其中@pert用户说:

In recent versions of the Arduino IDE(including 1.6.10) if you want to include libraries from the sketch folder you need to put them in a src subfolder. For example:

Blink  
|_Blink.ino  
|_src  
   |_BlinkLib  
       |_BlinkLib.h  


然后他说您可以包括以下内容:

#include "src/BlinkLib/BlinkLib.h"  


我没有尝试过,但是如果可行的话那将非常有用。试一试,让我知道它是否有效。请务必告诉我们您正在使用哪个OS和Arduino IDE版本。

在此处查看有关Github的其他讨论:https://github.com/arduino/Arduino/issues/5186

关于c++ - 如何将cpp文件添加到arduino项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55684371/

相关文章:

c++ - 让编译器在调用函数之前忽略设置参数寄存器

php - Apache http 服务器回复 418 ("I' m a teapot") - json 参数,使用来自 arduino 的 PUT 的 TCP 请求

arduino - 找不到 Arduino IDE VS Code

c++ - 为什么我的用于运行带障碍物传感器的蓝牙控制机器人的 Arduino 代码无法正常工作?

c++ - 如何将获取的字符串数据转换为字符数组?

c++ - 为什么本地图是 const static 时以下内容不起作用

c++ - 从 Unix 应用程序并行启动/停止应用程序

java - 更好地表达 "if false return false"构造

ios - 如何在 iOS 中获取 HM-10 Bluetooth LE 的特性

c++ - 添加冒号 ( :) to an unsigned char in C++