Несколько включений библиотеки только заголовков, вызывающей ошибки переопределения - PullRequest
1 голос
/ 16 июня 2019

Я использую библиотеку только для заголовков с именем 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"

Библиотека Nuklear уже включает в себя средства защиты заголовков, поэтому я не уверен, почему происходит эта ошибка. Любой совет?

Ответы [ 3 ]

5 голосов
/ 16 июня 2019

Из README на GitHub:

Эта библиотека содержится в одном заголовочном файле и может использоваться либо в режиме только заголовка, либо в режиме реализации. Режим «только заголовок» используется по умолчанию, когда включен, и позволяет включать этот заголовок в другие заголовки и не содержит фактической реализации.

Режим реализации требует определения макроса препроцессора NK_IMPLEMENTATION в одном файле .c / .cpp перед #include использованием этого файла, например ::

#define NK_IMPLEMENTATION
#include "nuklear.h"

Итак, только один из main.c и components.c должен включать #define NK_IMPLEMENTATION - но вы определяете его в обоих.

Fix

  • Удалить #define NK_IMPLEMENTATION из components.c.
  • Не включайте никакие другие заголовки Nuklear, кроме nuklear.h - инструкции не говорят вам сделать это (по крайней мере, не на поверхности; возможно, есть что-то еще, что говорит об этом, но ...).

В документации также отмечается:

ВАЖНО: Каждый раз, когда вы включаете "nuklear.h", вы должны определять одни и те же дополнительные флаги. Это очень важно, потому что это не приводит к ошибкам компилятора или к еще худшим повреждениям стека.

Вероятно, стоило бы иметь свой собственный заголовок - например, use_nuklear.h, хотя я уверен, что вы придумали более подходящее имя, которое содержит правильный набор NK_* параметров (все, кроме NK_IMPLEMENTATION) , Тогда #include "use_nuklear.h" в ваших исходных файлах. Таким образом, если (когда) вы измените параметры, у вас есть только одно место для изменений - и восстановление будет согласованным.

3 голосов
/ 16 июня 2019

Вы должны только #define NK_SDL_GL3_IMPLEMENTATION в одном из ваших исходных файлов .c перед вами #include "nuklear_sdl_gl3.h".

Файл nuklear_sdl_gl3.h содержит все определения функций, а также объявления функций, и вы хотите, чтобы определения были только в одном месте, или, как вы обнаружили, ваш компоновщик будет жаловаться.

0 голосов
/ 16 июня 2019

nuklear_sdl_gl3.h содержит данные и функции. Это просто очень плохо написано. Все определения должны быть в файлах .c, а в заголовочном файле должны быть только объявления, определения типов, объявления внешних переменных и статические встроенные функции.

Вы не можете включать этот файл более одного раза во весь проект. Охранники здесь не работают, так как они включены в различные модули компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...