Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Dear ImGui as a C++ module / import ImGui; #8358

Open
radjkarl opened this issue Jan 30, 2025 · 3 comments
Open

Using Dear ImGui as a C++ module / import ImGui; #8358

radjkarl opened this issue Jan 30, 2025 · 3 comments

Comments

@radjkarl
Copy link

radjkarl commented Jan 30, 2025

Version/Branch of Dear ImGui:

v1.91.8 WIP / docking

Back-ends:

imgui_impl_win32.cpp + imgui_impl_dx11.cpp

Compiler, OS:

MSVC 2022 C++latest

Full config/build information:

Dear ImGui 1.91.8 WIP (19174)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=202004
define: _WIN32
define: _WIN64
define: _MSC_VER=1942
define: _MSVC_LANG=202004
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_win32
io.BackendRendererName: imgui_impl_dx11
io.ConfigFlags: 0x00000000
io.ConfigViewportsNoDecoration
io.ConfigNavCaptureKeyboard
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 2 fonts, Flags: 0x00000000, TexSize: 512,512
io.DisplaySize: 1592.00,1046.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Details:

import ImGui;

I wanted to share current solution to use ImGui as a C++20/23 module. I replaced almost all header files in my projects with modules (besides std and opencv). Its clean you know - not sure that justifies the pain of migrating but here I am ...
Attached 2 files (just remove the *.txt) can be used as replacement to #include "imgui.h", imgui_internal.h and imgui_stdlib.h.

ImGui.ixx.txt
ImGui_base.ixx.txt

As this started as an experiment, I manually listed all structs, functions and enums (with their values). To make this future proven, at some point I ll either make a python script or use some clang feature to automate this process.

  1. ImGui_base.ixx
    This file exports all objects of aforementioned headers - excluding their macros.

  2. ImGui.ixx
    Exposes ImGui_base.ixx and redefines (some) macros as constexpr or normal functions.

Lessons learned

  • import <imgui.h> -> fail (for my toolchain importing headers doesn't work anyway)
  • add imgui_....h to precompiled headers -> fail
  • just export all from imgui.h in a module -> fail. All items to be exported need to be listed (including values of unscoped enums)
  • these modules only expose all objects via using ::something; or using ::ImGui::something;, so automating this task later on should be straight forward
  • because macros don't leak from modules, I had to redefine them as functions - fortunately this only affects a few
  • as we don't redefine objects (excl macros), mixing imgui headers together with this module seems to works fine, and the following compiles:
module;

//<< those headers you don't need anymore, but if you forget to exclude them, your module should still compile
#include "imgui.h"
#include "imgui_internal.h"
#include "imgui_stdlib.h"
//>>

export module something;

import ImGui;

export
namespace something
{
...
}

This issue is more a showcase than a request to change anything. At a later stage maybe Ill create a PR/Fork if someone is interested.
Just one question for the dear reader: imgui_internal.h incudes some math functions, like ImPow that are declared static, see
static inline float ImPow(float x, float y) { return powf(x, y); }
Is there any good reason for them be static? These ones I also had to redefine in the ImGui.ixx module.

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

// this is just an example of how I import ImGui as a c++ module

export module something;

import ImGui; // <- this module exposes most items from imgui.h, imgui_internal.h and imgui_stdlib.h

export
namespace something
{

    ImVec2 myFunc()
    {
       return ImGui::something();
    }
}
@ocornut ocornut changed the title import ImGui; Using Dear ImGui as a C++ module / import ImGui; Jan 30, 2025
@PathogenDavid
Copy link
Contributor

To make this future proven, at some point I ll either make a python script or use some clang feature to automate this process.

Dear Bindings (the automatically generated C wrapper for Dear ImGui) might be a good reference here. Maybe even a fork of it would make sense.

This issue is more a showcase than a request to change anything. At a later stage maybe Ill create a PR/Fork if someone is interested.

I've heard mostly bad things about C++ modules and have been meaning to give them a serious try at some point to form my own opinions. So I'd be interested to hear if you ever publishing something more formal! (Definitely don't do it for my sake though, this thread is already very helpful as-is.)

@stripe2933
Copy link

I've heard mostly bad things about C++ modules and have been meaning to give them a serious try at some point to form my own opinions. So I'd be interested to hear if you ever publishing something more formal! (Definitely don't do it for my sake though, this thread is already very helpful as-is.)

I’m using ImGui + GLFW-Vulkan backend with C++ modules, by creating my own symbol export file. This project can be cross-compiled with both Clang and MSVC, so I think some notorious thoughts for C++ module is little bit exaggerated.

I’m not aware of all the ImGui symbols; therefore, I’m currently exporting only the necessary symbols. However, it would be great to have a complete export list for every release so that I can stop triggering recompilation when I need to use a new symbol.

@radjkarl
Copy link
Author

Dear Bindings (the automatically generated C wrapper for Dear ImGui) might be a good reference here. Maybe even a fork of it would make sense.

I think this is a great idea. I looked up the project and once I upgrade to a new ImGui version I will create a script based to Dear Bindings to create the modules. - will post here. If it works well, Dear Bindings might be the place to host that script.

I've heard mostly bad things about C++ modules and have been meaning to give them a serious try at some point to form my own opinions. So I'd be interested to hear if you ever publishing something more formal! (Definitely don't do it for my sake though, this thread is already very helpful as-is.)

There were, especially in the early times, often compiler bugs that I had to work around. Nowadays they are less common. Compiling my project in full does take longer it would have taken using headers. Main reason is, that I cannot use import std as I also use opencv which breaks once I do. During compilation every header unit is compiled - often not in parallel due to dependencies to other modules. So every time std headers or opencv headers are included the are recompiled. I have a cmake project where those are precompiled - and that works well but its ugly as those headers are implicitly included. I can tell you though that a project not using headers at all will likely be compiling much faster. Incremental compilation for me did vastly improve without headers. My main focus is though on code quality. With modules you don't import any breaking macros. You don't need to worry about include positions - just list what you need. Unless you re-export a module from another one you import you ll also have to import it again which i find way cleaner. I think modules can change the c++ ecosystem for the better. They work for me. ImGui is a lucky example that we can actually get module-ready with very little effort. You see stripe2933 and I just use 'using ImGui_###' statements - only thing we need to manually re-define are static functions and macros. Fortunately there are not too many.
https://arewemodulesyet.org/ shows that there are next to no libraries that offer modules. I tried wrapping opencv headers into modules. Those contain a lot of very old code, that would need to be redefined. I failed there. I think for many projects you would need to replace the headers with modules - then need to modify the source files to do the same.... I saw some effort to use macros to depending on your setup either include headers or import modules. For projects like opencv with would be the only way forward. But its a lot of work.

Anyway - I post here when I have updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants