对ifdef块中的函数的未定义引用

问题描述 投票:0回答:2

我有以下问题:

我正在为一组与微控制器一起使用的传感器编写一个集合库。意思是我为传感器和摘要采用了大量的库,并在学生项目的统一库中简化了一些。

我使用#define结构来确定学生想要使用和连接的传感器。

例:

#define IR_SENSOR_USED

在库的.h和.cpp文件中,然后使用#ifdef-#endif对来定义和声明给定传感器的函数以及包含给定的库。

我的Sensors.h文件示例:

#ifdef IR_SENSOR_USED
  #include "SparkFun_GridEYE_AMG88/src/SparkFun_GridEYE_Arduino_Library.h"
  extern GridEYE grideye;
  void setup_ir_sensor();
  void read_ir_sensor();
  void enable_ir_interrupt(float lower, float upper, float hysteresis);
  void disable_ir_interrupt();
#endif

并从我的Sensors.cpp文件:

#ifdef IR_SENSOR_USED
void setup_ir_sensor() {
  Wire.begin(16, 17, 0x69);
  grideye.begin(0x69, Wire);
}

void read_ir_sensor() {
  for (int i = 0; i <= 64; i++) {
    sensor_values.ir_pixel_temp[i] = grideye.getPixelTemperature(i);
  }
  sensor_values.ir_device_temp = grideye.getDeviceTemperature();
}

void enable_ir_interrupt(float lower, float upper, float hysteresis) {...}

void disable_ir_interrupt() {...}
#endif

但是,只要我在.cpp文件中有#ifdef,如果我尝试调用setup()中的函数,我会收到以下错误:

sketch/Sensors.ino.cpp.o:(.literal._Z5setupv+0xc): undefined reference to `read_ir_sensor()'
sketch/Sensors.ino.cpp.o: In function `setup()':
.../Sensors/Sensors.ino:112: undefined reference to `read_ir_sensor()'
collect2: error: ld returned 1 exit status
exit status 1

如果我评论它们,代码执行正常。另一个功能(setup_sensors()),也在Sensors.h.cpp文件中,并没有被#ifdef包围也很好。

这是我的Sensors.ino草图:

#define IR_SENSOR_USED
//#define COLOR_SENSOR_USED
//#define ENV_SENSOR_USED
//#define TEMP_SENSOR_USED

#include "Sensors.h"

void setup() {
  sensor_setup();

  read_ir_sensor();
}

void loop() {
}

这是什么原因? (为什么)预处理器不能正确执行.cpp文件中的指令?

c++ arduino c-preprocessor undefined-reference esp32
2个回答
1
投票

正如评论和其他答案所指出的,任何#define指令仅在包含它们的文件中可见。所以有

#define IR_SENSOR_USED

Sensors.cpp中不会影响任何未在Sensors.cpp中编译的代码(重要的是,它会影响.h中包含的Sensors.cpp文件中包含的代码。但它不会影响其他#define文件中包含的任何内容。

比Arduino更复杂的构建环境有更好,更复杂的方法来处理这个问题,但Arduino世界并没有给你很多工具来处理这个问题。

我在Arduino世界中做的只是有一个名为.cpp的文件,其中包含我需要在项目范围内的所有config.h语句。我需要这些值的每个文件中的#define

因此,在您的情况下,您将所有定义显示在#include "config.h"中使用哪些设备,然后在每个依赖于它的文件的开头显示config.h

您甚至可以在#include "config.h"文件的开头包含它。我会考虑将两个文件分开,以便在需要配置的东西和有用的代码之间存在明确的界限。

我还在此文件中保留任何敏感值(wifi凭据,密码,API密钥),并将其从我在Github上发布的代码中排除。在它的位置,我包含一个“config-example.h”文件,其中包含所有指令但具有虚拟值,因此使用该代码的其他人可以编辑和重命名它。


1
投票

这个问题可能是Sensors.h的一个例子。

如果您希望库的用户选择他们需要的功能,那么将声明放在单独的头文件中会更有意义。例如,XY problem然后

IR_sensor.h

变得只是#define IR_SENSOR_USED #include "Sensors.h"

  • 如果库的大小是或关注的,可以选择将其拆分为单独的库。
  • 第三种选择是将功能提供为#include "IR_sensor.h"库。

确切答案:

这是什么原因? (为什么)预处理器不能正确执行.cpp文件中的指令?

最可能的原因是header-only不知道Sensors.cpp。定义在另一个未包含的文件中。

然而,即使在#define IR_SENSOR_USED中定义IR_SENSOR_USED,另一个问题就出现了:为每个可能的定义组合重新编译Sensors.cpp是必要的。否则,ifdefed-code将从编译中排除,并且无法通过调用Sensors.cpp在客户端上简单地启用。

© www.soinside.com 2019 - 2024. All rights reserved.