我有以下问题:
我正在为一组与微控制器一起使用的传感器编写一个集合库。意思是我为传感器和摘要采用了大量的库,并在学生项目的统一库中简化了一些。
我使用#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文件中的指令?
正如评论和其他答案所指出的,任何#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”文件,其中包含所有指令但具有虚拟值,因此使用该代码的其他人可以编辑和重命名它。
这个问题可能是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
在客户端上简单地启用。