我正在使用名为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库已经包含标题保护,因此我不确定为什么会发生此错误。有什么建议吗?
答案 0 :(得分:5)
从GitHub上的README:
该库自身包含在一个单独的头文件中,并且可以在仅头模式下或在实现模式下使用。仅标头模式在默认情况下会在包含时使用,并且允许将此标头包含在其他标头中,并且不包含实际的实现。
实施模式要求在
NK_IMPLEMENTATION
创建文件之前,先在一个.c
/.cpp
文件中定义预处理器宏#include
,例如:#define NK_IMPLEMENTATION #include "nuklear.h"
因此,main.c
和components.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文件中,并且只有声明,类型定义,外部变量声明和静态内联函数应位于头文件中。
您不能在整个项目中多次包含此文件。警卫在这里不起作用,因为它包含在不同的编辑单元中。