混合C和C ++时重复的符号

时间:2016-05-20 15:28:17

标签: c++ c cmake linker-errors sdl-2

我正在尝试通过SDL2 KISS(在第4页上找到)学习如何使用example provided in the manual项目/工具包/库事物。然而,每当我链接它时,它都会失败,引用重复的符号错误。 repo中提供的两个 example files 构建,编译并正常工作。

我的假设是,因为我正在尝试将手册中的示例代码编写到C ++文件中,并且库是纯C89的,所以会有一些愤怒的内部编译器爆炸。如果我使用相同的代码转发声明一个C函数,一切似乎都没问题,但我真的希望没有一堆C ++文件纯粹作为委托来调用C函数。

在项目readme(在第一段末尾)确实说一切都是C ++兼容的,并且实际上是以写入SDL2库的方式编写的 - 我可以毫无问题地使用它。似乎正确设置了SDL2 KISS标头,以便与C ++一起使用:

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
};
#endif

尽可能导致Undefined symbols for architecture x86_64链接器错误的原因,我有三个嫌疑人:我对将纯C与C ++混合的无知,我为项目编写的CMakeLists,或者库本身的问题(我觉得非常不可能)。我已经在几天内弄乱了不同的潜在解决方案,但没有遇到任何比向前声明更好的事情(再次,我不想这样做)。 Bellow你会找到确切的错误,我的main.cpp文件,其中只包含手册中的代码,以及我写的CMakeLists文件。发布的代码对我来说构建,但我可以发布正在工作的C ++文件,该文件向前声明一个C函数,如果这样做会有帮助。

从终端

发出错误
Scanning dependencies of target Test_KISS
[ 16%] Linking CXX executable bin/Test_KISS
duplicate symbol _kiss_border in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_green in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_progress_interval in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_click_interval in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_black in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_slider_padding in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_spacing in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_textfont_size in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_buttonfont_size in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_lightblue in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_blue in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_white in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_edge in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
ld: 13 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/Test_KISS] Error 1
make[1]: *** [CMakeFiles/Test_KISS.dir/all] Error 2
make: *** [all] Error 2

的main.cpp

#include "kiss_sdl.h"


void button_event(kiss_button *button, SDL_Event *e, int *draw, int *quit)
{
    if (kiss_button_event (button, e, draw))
        *quit = 1;
}

int main (int argc, char *argv[])
{

    SDL_Renderer *renderer;
    SDL_Event e;

    kiss_array objects;
    kiss_window window;
    kiss_label label;
    kiss_button button;

    char message[KISS_MAX_LENGTH];
    int draw = 1;
    int quit = 0;

    kiss_array_new (&objects);
    renderer = kiss_init ("Test KISS SDL", &objects, 320, 120);
    kiss_window_new (&window, NULL, 0, 0, 0, kiss_screen_width, kiss_screen_height);
    strcpy (message, "Hello, world!");

    kiss_label_new (&label, &window, message, window.rect.w / 2 - strlen (message) * kiss_textfont.advance / 2, window.rect.h / 2 - (kiss_textfont.fontheight + 2 * kiss_normal.h) / 2);
    label.textcolor.r = 255;

    kiss_button_new (&button, &window, "Okay", window.rect.w / 2 - kiss_normal.w / 2, label.rect.y + kiss_textfont.fontheight + kiss_normal.h);
    window.visible = 1;

    while (!quit)
    {

        SDL_Delay (10);
        while (SDL_PollEvent (&e))
        {

             if (e.type == SDL_QUIT)
                 quit = 1;

             kiss_window_event (&window, &e, &draw);
             button_event (&button, &e, &draw, &quit);
        }

        if (!draw)
            continue;

        SDL_RenderClear (renderer);
        kiss_window_draw (&window, renderer);
        kiss_label_draw (&label, renderer);
        kiss_button_draw (&button, renderer);
        SDL_RenderPresent (renderer);
        draw = 0;
    }

    kiss_clean (&objects);
    return 0;
}

CMakeLists

cmake_minimum_required(VERSION 3.3)
project(Test_KISS)


set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Test_KISS_SOURCE_DIR}/cmake")
set(BIN_DIR ${Test_KISS_SOURCE_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)


#Define Preprocessor Macros (RESDIR found in include/kiss_sdl.h)
add_definitions(-DRESDIR=\"../../resources/\")


find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIR})

find_package(SDL2_ttf REQUIRED)
include_directories(${SDL2_TTF_INCLUDE_DIR})

find_package(SDL2_image REQUIRED)
include_directories(${SDL2_IMAGE_INCLUDE_DIR})

include_directories(include)


add_executable(Test_KISS src/main.cpp include/kiss_draw.c include/kiss_general.c include/kiss_posix.c include/kiss_widgets.c)


target_link_libraries(Test_KISS ${SDL2_LIBRARY} ${SDL2_TTF_LIBRARY} ${SDL2_IMAGE_LIBRARY})
install(TARGETS Test_KISS RUNTIME DESTINATION ${BIN_DIR})

如果我可以提供更多帮助信息,请告诉我们!

谢谢!

2 个答案:

答案 0 :(得分:2)

kiss_sdl.h实际上定义众多变量:

double kiss_spacing;
int kiss_textfont_size, kiss_buttonfont_size;
int kiss_click_interval, kiss_progress_interval;
int kiss_slider_padding;
int kiss_border, kiss_edge;
int kiss_screen_width, kiss_screen_height;

#include个文件的每个C / C ++文件中定义这些变量。因此,您会得到重复的符号 - 因为重复的符号。

修复?修复代码以使其正确declares the variables instead of defining them

换句话说,代码被破坏了。

答案 1 :(得分:0)

现在修好了。 extern" C"虽然意味着它下面的声明就像C ++,其余的代码就像C一样编译,就像我的C89一样。如果使用C编译器编译,则使用c扩展名编译。正确理解这是解决问题的原因。

SDL2 https://github.com/actsl/kiss_sdl的简单通用GUI小部件工具包,由我编写。