dearimgui / dear_bindings

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

error: out-of-line definition of 'ImVector_Construct' #63

Closed techie-guy closed 6 months ago

techie-guy commented 7 months ago

I am halfway there on integrating this into a C project...

But I get this during compilation

==== Building cimgui (debug_native) ====
cimgui.cpp
cimgui.cpp:19:25: error: out-of-line definition of 'ImVector_Construct' does not match any declaration in namespace 'cimgui'
CIMGUI_API void cimgui::ImVector_Construct(void* vector)
                        ^~~~~~~~~~~~~~~~~~
cimgui.cpp:25:25: error: out-of-line definition of 'ImVector_Destruct' does not match any declaration in namespace 'cimgui'
CIMGUI_API void cimgui::ImVector_Destruct(void* vector)
                        ^~~~~~~~~~~~~~~~~
2 errors generated.
make[1]: *** [Makefile:207: obj/Native/Debug/cimgui.o] Error 1
make: *** [Makefile:46: cimgui] Error 2

The related premake5 snippet

project "cimgui"
    kind "SharedLib"
    language "C++"
    location "third-party/cimgui"

    buildoptions
    {
    "-fPIC"
    }

    includedirs
    {
    "third-party/cimgui/imgui",
        "third-party/cimgui/imgui/backends",
    }

    files
    {
    "third-party/cimgui/cimgui.h",
    "third-party/cimgui/cimgui.cpp",
    "third-party/cimgui/cimgui_impl_opengl3.h",
    "third-party/cimgui/cimgui_impl_opengl3.cpp",
    "third-party/cimgui/cimgui_impl_glfw.h",
    "third-party/cimgui/cimgui_impl_glfw.cpp",
    "third-party/cimgui/imgui/imgui.cpp",
    "third-party/cimgui/imgui/imgui_demo.cpp",
    "third-party/cimgui/imgui/imgui_draw.cpp",
    "third-party/cimgui/imgui/imgui_tables.cpp",
    "third-party/cimgui/imgui/imgui_widgets.cpp",
    "third-party/cimgui/imgui/imconfig.h",
    "third-party/cimgui/imgui/backends/imgui_impl_opengl3.h",
    "third-party/cimgui/imgui/backends/imgui_impl_opengl3.cpp",
    "third-party/cimgui/imgui/backends/imgui_impl_glfw.h",
        "third-party/cimgui/imgui/backends/imgui_impl_glfw.cpp",
    }

If I build the library directly using

clang++ cimgui-impl-glfw.cpp cimgui.cpp cimgui-impl-opengl.cpp imgui/imgui.cpp imgui/imgui_demo.cpp imgui/imgui_draw.cpp imgui/imgui_tables.cpp imgui/imgui_widgets.cpp imgui/backends/imgui_impl_glfw.cpp imgui/backends/imgui_impl_opengl3.cpp -fPIC -shared -I imgui -I imgui/backends -o final-lib.so

It compiles without any errors.

Then why does it throw that error on using premake5?

techie-guy commented 6 months ago

I commented out this part in cimgui.cpp and it builds with no errors

// Manual helpers
// These implement functionality that isn't in the original C++ API, but is useful to callers from other languages
CIMGUI_API void cimgui::ImVector_Construct(void* vector)
{
    // All ImVector classes are the same size, so it doesn't matter which we use for sizeof() here
    memset(vector, 0, sizeof(::ImVector<int>));
}

CIMGUI_API void cimgui::ImVector_Destruct(void* vector)
{
    // As with ImVector_construct(), it doesn't matter what the type parameter is here as we just want to get the
    // pointer and free it (without calling destructors or anything similar)
    ::ImVector<int>* real_vector = reinterpret_cast<::ImVector<int>*>(vector);
    if (real_vector->Data)
    {
        IM_FREE(real_vector->Data);
    }
}

Why was it giving the error in the first place?

techie-guy commented 6 months ago

One more question...

How am I supposed to build this library in order to get a static library, that can be linked to the C program?

If I try to generate a static library, I get linker errors for C++ standard library functions, during the final compilation process using the C compiler.

eg:

/usr/bin/ld: ./final-lib.a(imgui_demo.o): in function `ShowExampleAppDocuments(bool*)':imgui_demo.cpp:(.text+0x18e4): undefined reference to `__cxa_guard_acquire'
/usr/bin/ld: imgui_demo.cpp:(.text+0x1924): undefined reference to `__cxa_guard_release'
/usr/bin/ld: imgui_demo.cpp:(.text+0x1977): undefined reference to `__cxa_guard_abort'
/usr/bin/ld: imgui_demo.cpp:(.text+0x20b1): undefined reference to `__cxa_guard_acquire'
/usr/bin/ld: imgui_demo.cpp:(.text+0x20f1): undefined reference to `__cxa_guard_release'
/usr/bin/ld: imgui_demo.cpp:(.text+0x21ba): undefined reference to `__cxa_guard_abort'
/usr/bin/ld: ./final-lib.a(imgui_demo.o): in function `ShowExampleAppConsole(bool*)':
imgui_demo.cpp:(.text+0x2601): undefined reference to `__cxa_guard_acquire'

I am using the above premake5 snippet to generate a shared library which works.

ShironekoBen commented 6 months ago

So on the first issue, I'm a bit perplexed, as those two functions are declared in the header and the C++ file correctly, as far as I can see. Maybe somehow cimgui.h got included outside the namespace declaration before the body of cimgui.cpp was processed? (a precompiled header or forced include directive or similar?)

I can only assume that the premake file is adding some extra compiler switches that don't get turned on when you compile manually. I'd be inclined to suggest seeing if you can persuade premake to dump the command line it is using for the compile, and looking for differences.

If you remove those two functions then everything will work as long as you don't need to create an ImVector - depending on your use-case, you might be able to get away with that as there are relatively few APIs that require that. But I suspect that these are symptoms of a deeper problem and you may find that even if the code compiles/links it won't behave correctly.

Looking at your link error, my suspicion is that is also to do with mismatched compiler settings - __cxa_guard_acquire() and friends are used for the implementation of thread-safe static initialisation and automatically emitted by the compiled based on the C++ standard version you are targeting and/or the -fno-threadsafe-statics flag. I think what you're seeing here is also that one or more of your build steps has different settings and so that particular object file is trying to use those functions but elsewhere they are being omitted.

I hope some of that is of help!

techie-guy commented 6 months ago

Ahh, I found the fix for the first issue. I had a typo in the generator command(the extra --backend flag) python3 dear_bindings/dear_bindings.py --backend -o cimgui imgui/imgui.h --imconfig-path imgui/imconfig.h

As for the second issue, I don't think it is possible to create a static library and not get those errors. I previously tried cimgui and it also gave similar errors on try to get a static library. If there's anything I can do to get rid of those errors, please let me know.

One last thing, I get this redefinition error for GLFWwindow(Sorry, if this is annoying)

In file included from src/Application.c:8:
third-party/cimgui/cimgui_impl_glfw.h:39:29: error: typedef redefinition with different types ('struct GLFWwindow_t' vs 'struct GLFWwindow')
typedef struct GLFWwindow_t GLFWwindow;
                            ^
/usr/include/GLFW/glfw3.h:1186:27: note: previous definition is here
typedef struct GLFWwindow GLFWwindow;
                          ^
In file included from src/Application.c:8:
third-party/cimgui/cimgui_impl_glfw.h:40:30: error: typedef redefinition with different types ('struct GLFWmonitor_t' vs 'struct GLFWmonitor')
typedef struct GLFWmonitor_t GLFWmonitor;
                             ^
/usr/include/GLFW/glfw3.h:1174:28: note: previous definition is here
typedef struct GLFWmonitor GLFWmonitor;
                           ^
2 errors generated.

I commented this out and added include for GLFW for a temporary fix in cimgui_impl_glfw.h

//#include <GLFW/glfw3.h>
typedef struct GLFWwindow_t GLFWwindow;
typedef struct GLFWmonitor_t GLFWmonitor;

How can I fix this?

ShironekoBen commented 6 months ago

Glad you got one of the issues fixed at least!

On the static library front, the only other thing that springs to mind is to check if you are linking the correct standard library (probably libc++ in this case?)... if it's not that then I'm afraid I'm as much in the dark as you are.

As for GLFWwindow and GLFWmonitor, oops - you're entirely right! As those are typedefs from external code applying the normal renaming rules breaks things. Fortunately there's already a mechanism in Dear Bindings to prevent that for specific symbols, so I've added those two to the list - 71ed1905a53aede13bf500dcf4b99f6c7d8b021d should fix them. If there's still a problem there, or you find another one I've missed just let me know and I'll add it to the list as well.

Thanks for the report!

techie-guy commented 6 months ago

Thanks for the fix for the GLFW issue!

The linking issue seems to be solved now. I added stdc++ to links of the project, and it stopped giving me those errors.

I have integrated this library into my C project.

Thank You for helping me!