【发布时间】:2019-02-28 19:07:29
【问题描述】:
我继承了一些代码*,它在头文件 (a_A.h) 中声明和定义了一个结构。此结构位于包含层次结构树的顶部文件中,其符号如下所示:
file: t_T.h (#includes "c_C.h") //defines a struct
file: c_C.h (#includes "h_H.h")
file: h_H.h (#includes "a_C.h")
file: a_C.h (#includes <stdio.h>)
每个标头都有适当的标头保护,并且在作为文件的平面集合查看时似乎是非递归的。但是,文件 c_C.h 和 a_C.h 位于同一个库中。而 h_H.h 位于不同的库中。从图书馆的角度来看,这象征性地表现为:
t_T.h (includes a file from Lib_C)
Lib_C: (includes a file from Lib_H)
Lib_H (includes a file from Lib_C)
这是递归的,可能是我编译代码时重新定义问题的原因(链接器抱怨文件 a_C.h 中的结构被重新定义)。
1) 我是否正确识别了问题?
2) 如果是这样,为什么?我猜想库中的链接对象对链接器来说是平坦的(即它们已经丢失了层次结构上下文)。如果猜对了,那么:
3) 我是否应该考虑将标头保护限制在其各自库的范围内?
以下是问题窗口中的错误说明:
symbol "ov5642_1280x960_RAW" redefined: first defined in "./TakePhoto.obj"; redefined in "./ArduCam/ov5642_Config.obj"
./TakePhoto 中的标题:
#ifndef TAKEPHOTO_H
#define TAKEPHOTO_H
#include "ov5642_Config.h"
#include "HAL_ArduCAM.h"
...
#endif /* TAKEPHOTO_H_ */
./ArduCAM/ov5642_Config.h 中的标头:
#ifndef ARDUCAM_OV5642_CONFIG_H_
#define ARDUCAM_OV5642_CONFIG_H_
#include "HAL_ArduCAM.h"
#include "ov5642_Sensor_Values.h"
....
#endif /* ARDUCAM_OV5642_CONFIG_H_ */
HAL_ArduCAM 中的标头
#ifndef HAL_ArduCAM_h
#define HAL_ArduCAM_h
#include <stdint.h>
#include "driverlib.h"
....
#endif /* HAL_ArduCAM_h */
ov5642_Sensor_Values.h 有以下内容
#ifndef ARDUCAM_OV5642_SENSOR_VALUES_H_
#define ARDUCAM_OV5642_SENSOR_VALUES_H_
#include <stdint.h>
const struct sensor_reg ov5642_1280x960_RAW[] =
{
{0x3103,0x93},
{0x3008,0x02},
{0x3017,0x7f},
.....
#endif /* ARDUCAM_OV5642_SENSOR_VALUES_H_ */
OV5642_Sensor_Values 的内容似乎被复制了两次,一次用于 TakePhoto,一次用于 ovV5642_Config,尽管它们有标头保护。我最初的想法是存在递归依赖关系但没有找到它。
好的,我在下面粘贴了一个示例。此示例中有五个文件,三个文件(bar.h、foo.h、foo.c 驻留在库中),其他两个文件(foo1.h、foo1.c)不存在。请注意,foo.h 包含 bar.h,而 foo1 包含 foo.h 和 bar.h。
我推测当预处理器复制到 foo.h 时,bar.h 的保护标头不会被保留。因此,当 foo1 包含 bar.h 和 foo.h 时,就会出现符号重新定义。所以回答我自己的问题,不,这不是图书馆问题。不保留标题保护似乎是我的问题的可能原因。
它们粘贴在下面。
/*
* bar.h
*
*/
#ifndef ARDUCAM_BAR_H_
#define ARDUCAM_BAR_H_
#include <stdint.h>
typedef struct regStruct {
uint16_t reg;
uint8_t val;
} regStruct;
const struct regStruct regArray[] =
{
{0x3103,0x03},
{0x3104,0x03},
{0x3008,0x82},
{0xffff,0xff},
};
const struct regStruct tinyArray[] =
{
{0x3106,0x03},
{0x3003,0x82},
{0xffff,0xff},
};
#endif /* ARDUCAM_BAR_H_ */
/*
* foo.h
*
*
*/
#ifndef ARDUCAM_FOO_H_
#define ARDUCAM_FOO_H_
#include <stdint.h>
#include <stdio.h>
#include "bar.h" //including this file causes redefinition
typedef struct Init_Parameters {
//! Select sensor resolution
//! options.
//! \n Valid values are:
//! - \b big
//! - \b small
//! - \b tiny
uint8_t size;
} Init_Parameters;
uint8_t Sensor_Init(Init_Parameters *param);
typedef enum {
small=0,
big,
tiny
} select_size;
#endif /* ARDUCAM_FOO_H_ */
/*
* foo.c
*
*
*/
#include "foo.h"
uint8_t Sensor_Init(Init_Parameters *param)
{
switch(param->size)
{
case big:
break;
case small:
break;
case tiny:
break;
}
return 0x01;
}
/*
* foo1.h
*
* Created on: Feb 28, 2019
* Author: jnadi
*/
#ifndef FOO1_H_
#define FOO1_H_
#include "foo.h"
#include "bar.h"
#endif /* FOO1_H_ */
/*
* foo1.c
*
* Created on: Feb 28, 2019
* Author: jnadi
*/
#include "foo1.h"
void Camera_Init(){
Init_Parameters setParams; //create instance
setParams.size=big;
Sensor_Init(&setParams);
}
【问题讨论】:
-
你能发帖minimal reproducible example吗?就像提到的所有文件的最小内容一样,它会重现问题。
-
我面临着让这段代码正常工作的压力,目前正在重组代码以避免递归库问题。我需要一段时间才能这样做。我曾希望我的描述就足够了
-
“文件 c_C.h 和 a_C.h 位于同一个库中”是什么意思?头文件可能会声明函数,而这些函数定义可能来自特定的库,也许这就是您的意思。但是使用“reside”这个词似乎意味着你误解了头文件和库之间的关系。特别是,我不知道“t_T.h(包括来自 Lib_C 的文件)”是什么意思。您不能包含库中的文件,尽管您可以包含可能来自用于构建库的源树的文件。
-
请编辑问题并添加来自链接器的完整且未编辑错误消息。我认为您误解了它的含义,因此在错误的地方寻找问题。
-
你好zwoi。我添加了来自链接器的消息。我真的希望我误解了这个错误。我还添加了头文件,其中包括包含重新定义的“ov5642_1280x960_RAW”符号的文件。