仅头文件库的多个包含导致重新定义错误

时间:2019-06-16 16:02:24

标签: c gcc nuklear

我正在使用名为Nuklear的仅标头库。这是仅标头的库。使用来自不同文件的多个包含项时遇到麻烦。它返回一个多定义示例:

...
obj/main.o:main.c:(.text+0x4a52b): multiple definition of `nk_sdl_font_stash_begin'
obj/components.o:components.c:(.text+0x4a56f): first defined here
obj/main.o:main.c:(.text+0x4a563): multiple definition of `nk_sdl_font_stash_end'
obj/components.o:components.c:(.text+0x4a5a7): first defined here
obj/main.o:main.c:(.text+0x4a5f4): multiple definition of `nk_sdl_handle_event'
obj/components.o:components.c:(.text+0x4a638): first defined here
obj/main.o:main.c:(.text+0x4ac9f): multiple definition of `nk_sdl_shutdown'
obj/components.o:components.c:(.text+0x4ace3): first defined here

我正在尝试将该库包含到2个文件中。

main.c

#define SDL_MAIN_HANDLED
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>

#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_SDL_GL3_IMPLEMENTATION
#include "nuklear.h"
#include "nuklear_sdl_gl3.h"
#include "components.h"
...

components.c

#define SDL_MAIN_HANDLED
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>

#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_SDL_GL3_IMPLEMENTATION
#include "nuklear.h"
#include "nuklear_sdl_gl3.h"

Nuclear库已经包含标题保护,因此我不确定为什么会发生此错误。有什么建议吗?

3 个答案:

答案 0 :(得分:5)

从GitHub上的README:

  

该库自身包含在一个单独的头文件中,并且可以在仅头模式下或在实现模式下使用。仅标头模式在默认情况下会在包含时使用,并且允许将此标头包含在其他标头中,并且不包含实际的实现。

     

实施模式要求在NK_IMPLEMENTATION创建文件之前,先在一个.c / .cpp文件中定义预处理器宏#include,例如:

#define NK_IMPLEMENTATION
#include "nuklear.h"

因此,main.ccomponents.c中只有一个应包含#define NK_IMPLEMENTATION —但您必须在两者中都定义它。

修复

  • #define NK_IMPLEMENTATION中删除components.c
  • 除了nuklear.h之外,不要包括任何其他Nuklear标头-指令不会告诉您这样做(至少不在表面上;也许其他地方有这样的意思,但是……)。

文档还指出:

  

重要提示:每次添加"nuklear.h"时,都必须定义相同的可选标志。这一点非常重要,不要这样做会导致编译器错误或什至更严重的堆栈损坏。

也许值得拥有自己的标头-例如use_nuklear.h,尽管我敢肯定您会想到一个更好的名称-其中包含正确的NK_*选项集(除NK_IMPLEMENTATION)。然后在源文件中#include "use_nuklear.h"。这样,如果(当)更改选项,则只有一个地方可以更改-并且重建将是一致的。

答案 1 :(得分:3)

#define NK_SDL_GL3_IMPLEMENTATION之前,您仅应{.1}}中的一个.c源文件中。

nuklear_sdl_gl3.h文件包含所有函数定义以及函数声明,并且您只希望将这些定义放在一个地方,或者,正如您所发现的,链接器会抱怨。

答案 2 :(得分:0)

nuklear_sdl_gl3.h包含数据和函数。它只是写得很糟糕。所有定义都应位于.c文件中,并且只有声明,类型定义,外部变量声明和静态内联函数应位于头文件中。

您不能在整个项目中多次包含此文件。警卫在这里不起作用,因为它包含在不同的编辑单元中。