diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 2214ffd1d..03a457082 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -423,6 +423,7 @@ static ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code) bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_android.cpp b/backends/imgui_impl_android.cpp index 7dd2afc2e..b0c463931 100644 --- a/backends/imgui_impl_android.cpp +++ b/backends/imgui_impl_android.cpp @@ -263,6 +263,8 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event) bool ImGui_ImplAndroid_Init(ANativeWindow* window) { + IMGUI_CHECKVERSION(); + g_Window = window; g_Time = 0.0; diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index a440eb3ed..9691b49fd 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -534,6 +534,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects() bool ImGui_ImplDX10_Init(ID3D10Device* device) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index c55c2621a..167bda673 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -546,6 +546,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 67334c83f..32f1622cd 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -702,6 +702,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index 7e89bb964..3eff9ab5d 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -285,6 +285,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) bool ImGui_ImplDX9_Init(IDirect3DDevice9* device) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 4b4f61525..883917875 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -556,6 +556,7 @@ void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows) static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); //printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED); diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index 5dada3037..d8ffc9073 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -167,6 +167,7 @@ static ImGuiKey ImGui_ImplGLUT_KeyToImGuiKey(int key) bool ImGui_ImplGLUT_Init() { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); #ifdef FREEGLUT io.BackendPlatformName = "imgui_impl_glut (freeglut)"; diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 29534d510..f9fd1087e 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -79,7 +79,6 @@ struct ImGui_ImplMetal_Data ImGui_ImplMetal_Data() { memset(this, 0, sizeof(*this)); } }; -static ImGui_ImplMetal_Data* ImGui_ImplMetal_CreateBackendData() { return IM_NEW(ImGui_ImplMetal_Data)(); } static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; } static void ImGui_ImplMetal_DestroyBackendData(){ IM_DELETE(ImGui_ImplMetal_GetBackendData()); } @@ -125,8 +124,11 @@ bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device) bool ImGui_ImplMetal_Init(id device) { - ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_CreateBackendData(); ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); + IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); + + ImGui_ImplMetal_Data* bd = IM_NEW(ImGui_ImplMetal_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_metal"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 115aaac56..3eb092afd 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -83,6 +83,7 @@ static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData() bool ImGui_ImplOpenGL2_Init() { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 2d492f750..189371f36 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -275,6 +275,7 @@ struct ImGui_ImplOpenGL3_VtxAttribState bool ImGui_ImplOpenGL3_Init(const char* glsl_version) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Initialize our loader diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 38b278203..322798022 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -84,7 +84,6 @@ struct ImGui_ImplOSX_Data ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); } }; -static ImGui_ImplOSX_Data* ImGui_ImplOSX_CreateBackendData() { return IM_NEW(ImGui_ImplOSX_Data)(); } static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; } static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); } @@ -392,13 +391,15 @@ IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view) { bool ImGui_ImplOSX_Init(NSView* view) { ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_CreateBackendData(); - io.BackendPlatformUserData = (void*)bd; + IMGUI_CHECKVERSION(); + IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); // Setup backend capabilities flags + ImGui_ImplOSX_Data* bd = IM_NEW(ImGui_ImplOSX_Data)(); + io.BackendPlatformUserData = (void*)bd; + io.BackendPlatformName = "imgui_impl_osx"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) //io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) - io.BackendPlatformName = "imgui_impl_osx"; bd->Observer = [ImGuiObserver new]; diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index b7fe7645f..892fe9050 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -400,6 +400,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); // Check and store if we are on a SDL backend that supports global mouse position diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 3aee74a9b..1a5c78576 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -369,6 +369,7 @@ static void ImGui_ImplSDL3_SetupPlatformHandles(ImGuiViewport* viewport, SDL_Win static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void* sdl_gl_context) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); IM_UNUSED(sdl_gl_context); // Unused in this branch diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp index 49caa7d0a..bee874687 100644 --- a/backends/imgui_impl_sdlrenderer2.cpp +++ b/backends/imgui_impl_sdlrenderer2.cpp @@ -63,6 +63,7 @@ static ImGui_ImplSDLRenderer2_Data* ImGui_ImplSDLRenderer2_GetBackendData() bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!"); diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index 8cb3bb63b..2a86f859a 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -59,6 +59,7 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData() bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!"); diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 7d1c230c4..ad233f44e 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1092,6 +1092,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) } ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 7c6bc3b99..bf741e1a4 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -724,6 +724,7 @@ void ImGui_ImplWGPU_InvalidateDeviceObjects() bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index bf852c539..248cf521c 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -146,6 +146,7 @@ static void ImGui_ImplWin32_UpdateKeyboardCodePage() static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); INT64 perf_frequency, perf_counter; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 150dde530..60d605bb9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -44,6 +44,9 @@ Breaking changes: Other changes: - Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041) [@prabuinet] +- Backends: all backends + demo now call IMGUI_CHECKVERSION() to verify ABI compatibility between caller + code and compiled version of Dear ImGui. If you get an assert it most likely mean you have a build issue, + read comments near the assert. (#7568) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 604dac2b4..4704f89b2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9639,8 +9639,8 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags // [SECTION] ERROR CHECKING //----------------------------------------------------------------------------- -// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui. -// This is called by IMGUI_CHECKVERSION(). +// Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues. +// Called by IMGUI_CHECKVERSION(). // Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit // If this triggers you have mismatched headers and compiled code versions. // - It could be because of a build issue (using new headers with old compiled code) @@ -9653,12 +9653,12 @@ bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si { bool error = false; if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatched version string!"); } - if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } + if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } - if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } - if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } - if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } - if (sz_idx != sizeof(ImDrawIdx)) { error = true; IM_ASSERT(sz_idx == sizeof(ImDrawIdx) && "Mismatched struct layout!"); } + if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } + if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } + if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } + if (sz_idx != sizeof(ImDrawIdx)) { error = true; IM_ASSERT(sz_idx == sizeof(ImDrawIdx) && "Mismatched struct layout!"); } return !error; } diff --git a/imgui.h b/imgui.h index 38d589b77..e37fb202d 100644 --- a/imgui.h +++ b/imgui.h @@ -90,6 +90,8 @@ Index of this file: #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers! #define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. + +// Check that version and structures layouts are matching between compiled imgui code and caller. Read comments above DebugCheckVersionAndDataLayout() for details. #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fc576c8b9..f144572b9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -266,6 +266,9 @@ void ImGui::ShowDemoWindow(bool* p_open) // Most functions would normally just assert/crash if the context is missing. IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!"); + // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues. + IMGUI_CHECKVERSION(); + // Examples Apps (accessible from the "Examples" menu) static bool show_app_main_menu_bar = false; static bool show_app_console = false;