【问题标题】:undefined reference to function inside ifdef block对 ifdef 块内函数的未定义引用
【发布时间】:2019-03-06 10:56:17
【问题描述】:

我有以下问题:

我正在为一组与微控制器一起使用的传感器编写一个集合库。这意味着我使用了很多传感器库,并在学生项目的统一库中对它们进行了抽象和简化。

我使用#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文件中的指令?

【问题讨论】:

  • 您确实使用Sensors.cpp(或从它创建的目标文件)构建?并且宏IR_SENSOR_USED为所有源文件定义的?
  • #define IR_SENSOR_USED 在哪里?
  • 在我的Sensors.ino 中,第一行是#define IR_SENSOR_USED,然后是#include "Sensors.h"
  • 所以在构建Sensors.cpp时没有定义?请记住,您的源文件是单独构建的,并且预处理器指令(如宏定义)仅适用于单个translation units
  • 不是这样吗?我以为这会奏效。如果不是这样,我的整个方法就有点没用了,不是吗?我还能如何完成我想做的事情?

标签: c++ arduino c-preprocessor undefined-reference esp32


【解决方案1】:

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

#define IR_SENSOR_USED

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

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

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

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

您甚至可以在 Sensors.h 文件的开头包含它。我会考虑将这两个文件分开,以便在需要配置的内容和有用的代码之间有明确的界限。

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

【讨论】:

    【解决方案2】:

    这个问题可能是XY problem 的一个实例。

    如果您希望库的用户选择他们需要的功能,将声明放在单独的标题中会更有意义。例如,IR_sensor.h 然后

    #define IR_SENSOR_USED
    #include "Sensors.h"
    

    变成#include "IR_sensor.h"

    • 如果库的大小不合适,可以选择将其拆分为单独的库。

    • 第三个选项是将功能作为header-only 库提供。

    确切答案:

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

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

    但是,即使 IR_SENSOR_USED 将在 Sensors.cpp 中定义,也会出现另一个问题:需要为每个可能的定义组合重新编译 Sensors.cpp。否则 ifdefed-code 将被排除在编译之外,并且不能通过调用 #define 在客户端简单地启用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-14
      • 2021-10-28
      • 2019-09-05
      • 2011-09-19
      • 2017-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多