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

Bug*_*rUK 1 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
Run Code Online (Sandbox Code Playgroud)

我试图将库包含到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"
...
Run Code Online (Sandbox Code Playgroud)

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"
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*ler 6

从GitHub上的README:

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

实现模式需要NK_IMPLEMENTATION.c/ .cpp文件中定义一个预处理器宏,然后再#include对该文件进行定义,例如:

#define NK_IMPLEMENTATION
#include "nuklear.h"
Run Code Online (Sandbox Code Playgroud)

因此,只有一个main.c,并components.c应包括#define NK_IMPLEMENTATION-但你在这两个定义。

固定

  • #define NK_IMPLEMENTATION从中删除components.c
  • 请勿包含任何其他Nuklear标头nuklear.h-指令不会告诉您这样做(至少不在表面上;也许在其他地方有这样的内容,但是…)。

该文档还指出:

重要说明:每次包含时"nuklear.h",都必须定义相同的可选标志。这一点非常重要,不要这样做会导致编译器错误,甚至导致更糟的堆栈损坏。

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