dearimgui / dear_bindings

C header (and language binding metadata) generator for Dear ImGui
MIT License
221 stars 12 forks source link

Compilation with GCC fails due to unresolved externals #13

Closed rokups closed 2 years ago

rokups commented 2 years ago
~/src/imgui/dear_bindings % g++ -I../imgui main.c cimgui.cpp ../imgui/imgui.cpp ../imgui/imgui_demo.cpp ../imgui/imgui_draw.cpp ../imgui/imgui_tables.cpp ../imgui/imgui_widgets.cpp -lm

/bin/ld: /tmp/ccvwzsli.o: in function `main':
main.c:(.text+0x1f): undefined reference to `ImGui_CreateContext()'
/bin/ld: main.c:(.text+0x24): undefined reference to `ImGui_GetIO()'
/bin/ld: main.c:(.text+0x4f): undefined reference to `ImFontAtlas_GetTexDataAsRGBA32(ImFontAtlas_t*, unsigned char**, int*, int*)'
/bin/ld: main.c:(.text+0xac): undefined reference to `ImGui_NewFrame()'
/bin/ld: main.c:(.text+0xc0): undefined reference to `ImGui_Text(char const*, ...)'
/bin/ld: main.c:(.text+0xeb): undefined reference to `ImGui_SliderFloat(char const*, float*, float, float)'
/bin/ld: main.c:(.text+0x141): undefined reference to `ImGui_Text(char const*, ...)'
/bin/ld: main.c:(.text+0x146): undefined reference to `ImGui_ShowDemoWindow()'
/bin/ld: main.c:(.text+0x14b): undefined reference to `ImGui_Render()'
/bin/ld: main.c:(.text+0x16d): undefined reference to `ImGui_DestroyContext()'
collect2: error: ld returned 1 exit status

My understanding is that GCC uses C++ name mangling because cimgui.h is included within a namespace. Moving cimgui.h out of namespace creates name collisions between generated and original enums.

// dear imgui: "null" example application
// (compile and link imgui, create context, run headless with NO INPUTS, NO GRAPHICS OUTPUT)
// This is useful to test building, but you cannot interact with anything here!
#include <stdio.h>
// FIXME: Remove when #12 is fixed.
#ifndef ImDrawIdx
typedef unsigned short ImDrawIdx;
#endif // #ifndef ImDrawIdx
#include "cimgui.h"

int main(int, char**)
{
    //IMGUI_CHECKVERSION();
    ImGui_CreateContext();
    ImGuiIO_t* io = ImGui_GetIO();

    // Build atlas
    unsigned char* tex_pixels = NULL;
    int tex_w, tex_h;
    ImFontAtlas_GetTexDataAsRGBA32(io->Fonts, &tex_pixels, &tex_w, &tex_h);

    for (int n = 0; n < 20; n++)
    {
        printf("NewFrame() %d\n", n);
        io->DisplaySize.x = 1920;
        io->DisplaySize.y = 1080;
        io->DeltaTime = 1.0f / 60.0f;
        ImGui_NewFrame();

        static float f = 0.0f;
        ImGui_Text("Hello, world!");
        ImGui_SliderFloat("float", &f, 0.0f, 1.0f);
        ImGui_Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io->Framerate, io->Framerate);
        ImGui_ShowDemoWindow();

        ImGui_Render();
    }

    printf("DestroyContext()\n");
    ImGui_DestroyContext();
    return 0;
}
PathogenDavid commented 2 years ago

You're actually in the opposite situation, by using g++ you're building main.c as C++. (g++ doesn't try to auto-detect the language like gcc does.) You can either build them separately or specify the language explicitly:

g++ -I../imgui -x c main.c -x c++ cimgui.cpp ../imgui/imgui.cpp ../imgui/imgui_demo.cpp ../imgui/imgui_draw.cpp ../imgui/imgui_tables.cpp ../imgui/imgui_widgets.cpp

(There's an additional unrelated issue with extern "C" being combined with static. Remove the #define CIMGUI_API extern "C" in cimgui.cpp to fix that temporarily. More info here: https://github.com/dearimgui/dear_bindings/issues/14)


Even though C++ users shouldn't really be using cimgui.h, it should include an extern "C" block when it's built as C++ to protect against this scenario. IE:

#ifndef IMGUI_H

#ifdef __cplusplus
extern "C"
{
#endif

// dear imgui, v1.84 WIP
// ...header contents goes here...

#ifdef __cplusplus
}
#endif
#endif

After this change, the explicit extern "C" block in the generated cimgui.cpp can be removed.

rokups commented 2 years ago

This i was not aware of, thank you! Explicitly specifying language worked, sample application builds without issues. I will add it to CI then. 🤝

PathogenDavid commented 2 years ago

No problem! It's definitely not the most intuitive, my initial instinct is always g++ should be the auto-detecting one too.

ShironekoBen commented 2 years ago

I think that with the recent changes to add extern "C" to the header this should work now either way, but let me know if something is still broken!

rokups commented 2 years ago

Can confirm compilation with g++ without explicitly specifying source code type now works. Thanks! 🙏🏻