1

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

...
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 个文件中。

主程序

#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"
...

组件.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"

Nuklar 库已经包含标头保护,所以我不确定为什么会发生这个错误。有什么建议吗?

4

3 回答 3

7

来自 GitHub 上的 README:

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

实现方式需要在ing 这个文件之前NK_IMPLEMENTATION在一个.c/文件中定义预处理器宏,例如:.cpp#include

#define NK_IMPLEMENTATION
#include "nuklear.h"

因此,只有其中一个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"在你的源文件中。这样,如果(当)您更改选项时,您只有一个地方可以更改 - 并且重建将保持一致。

于 2019-06-16T16:49:01.417 回答
3

您应该只#define NK_SDL_GL3_IMPLEMENTATION在您的 .c 源文件之一之前#include "nuklear_sdl_gl3.h".

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

于 2019-06-16T16:14:02.760 回答
0

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

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

于 2019-06-16T16:13:56.603 回答