Added commentary about DLL boundaries. Added GetAllocatorFunctions(). Tidying up. (#3836)

This commit is contained in:
ocornut 2021-02-24 19:34:42 +01:00
parent 3f5bb5939a
commit 6f4b9c65ae
4 changed files with 47 additions and 26 deletions

View File

@ -50,6 +50,7 @@ Other Changes:
with ImGuiSliderFlags_AlwaysClamp + only one of either p_min or p_max set. (#3824) [@harry75369] with ImGuiSliderFlags_AlwaysClamp + only one of either p_min or p_max set. (#3824) [@harry75369]
- Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible - Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible
area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825) area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825)
- Added GetAllocatorFunctions() to facilitate sharing allocators accross DLL boundaries. (#3836)
- ImDrawList: AddCircle, AddCircleFilled(): Tweaked default segment count calculation to honor MaxError - ImDrawList: AddCircle, AddCircleFilled(): Tweaked default segment count calculation to honor MaxError
with more accuracy. Made default segment count always even for better looking result. (#3808) [@thedmd] with more accuracy. Made default segment count always even for better looking result. (#3808) [@thedmd]
- ImDrawList: AddCircle, AddCircleFilled(): New default for style. - ImDrawList: AddCircle, AddCircleFilled(): New default for style.

View File

@ -20,7 +20,9 @@
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport ) //#define IMGUI_API __declspec( dllimport )

View File

@ -911,27 +911,33 @@ static void UpdateViewportsNewFrame();
// [SECTION] CONTEXT AND MEMORY ALLOCATORS // [SECTION] CONTEXT AND MEMORY ALLOCATORS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// DLL users:
// - Heaps and globals are not shared across DLL boundaries!
// - You will need to call SetCurrentContext() + SetAllocatorFunctions() for each static/DLL boundary you are calling from.
// - Same apply for hot-reloading mechanisms that are reliant on reloading DLL (note that many hot-reloading mechanism works without DLL).
// - Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// - Confused? In a debugger: add GImGui to your watch window and notice how its value changes depending on your current location (which DLL boundary you are in).
// Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL. // Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
// ImGui::CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext(). // - ImGui::CreateContext() will automatically set this pointer if it is NULL.
// 1) Important: globals are not shared across DLL boundaries! If you use DLLs or any form of hot-reloading: you will need to call // Change to a different context by calling ImGui::SetCurrentContext().
// SetCurrentContext() (with the pointer you got from CreateContext) from each unique static/DLL boundary, and after each hot-reloading. // - Important: Dear ImGui functions are not thread-safe because of this pointer.
// In your debugger, add GImGui to your watch window and notice how its value changes depending on which location you are currently stepping into. // If you want thread-safety to allow N threads to access N different contexts:
// 2) Important: Dear ImGui functions are not thread-safe because of this pointer. // - Change this variable to use thread local storage so each thread can refer to a different context, in your imconfig.h:
// If you want thread-safety to allow N threads to access N different contexts, you can: // struct ImGuiContext;
// - Change this variable to use thread local storage so each thread can refer to a different context, in imconfig.h: // extern thread_local ImGuiContext* MyImGuiTLS;
// struct ImGuiContext; // #define GImGui MyImGuiTLS
// extern thread_local ImGuiContext* MyImGuiTLS; // And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword.
// #define GImGui MyImGuiTLS // - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
// And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword. // - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
// - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 // - DLL users: read comments above.
// - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
#ifndef GImGui #ifndef GImGui
ImGuiContext* GImGui = NULL; ImGuiContext* GImGui = NULL;
#endif #endif
// Memory Allocator functions. Use SetAllocatorFunctions() to change them. // Memory Allocator functions. Use SetAllocatorFunctions() to change them.
// If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file. // - You probably don't want to modify those mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
// Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction. // - DLL users: read comments above.
#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS #ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); return malloc(size); } static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); return malloc(size); }
static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); free(ptr); } static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); free(ptr); }
@ -939,10 +945,9 @@ static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_d
static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; } static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; }
static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); } static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
#endif #endif
static ImGuiMemAllocFunc* GImAllocatorAllocFunc = MallocWrapper;
static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper; static ImGuiMemFreeFunc* GImAllocatorFreeFunc = FreeWrapper;
static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper; static void* GImAllocatorUserData = NULL;
static void* GImAllocatorUserData = NULL;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) // [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
@ -3330,13 +3335,21 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx)
#endif #endif
} }
void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data) void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc* alloc_func, ImGuiMemFreeFunc* free_func, void* user_data)
{ {
GImAllocatorAllocFunc = alloc_func; GImAllocatorAllocFunc = alloc_func;
GImAllocatorFreeFunc = free_func; GImAllocatorFreeFunc = free_func;
GImAllocatorUserData = user_data; GImAllocatorUserData = user_data;
} }
// This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space)
void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc** p_alloc_func, ImGuiMemFreeFunc** p_free_func, void** p_user_data)
{
*p_alloc_func = GImAllocatorAllocFunc;
*p_free_func = GImAllocatorFreeFunc;
*p_user_data = GImAllocatorUserData;
}
ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas) ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
{ {
ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas); ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);

15
imgui.h
View File

@ -193,6 +193,8 @@ typedef void* ImTextureID; // User data for rendering backend to identi
typedef unsigned int ImGuiID; // A unique ID used by widgets, typically hashed from a stack of string. typedef unsigned int ImGuiID; // A unique ID used by widgets, typically hashed from a stack of string.
typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText() typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText()
typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints() typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints()
typedef void* (ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()
typedef void (ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()
// Character types // Character types
// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) // (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)
@ -255,8 +257,9 @@ struct ImVec4
namespace ImGui namespace ImGui
{ {
// Context creation and access // Context creation and access
// Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between imgui contexts. // - Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between contexts.
// None of those functions is reliant on the current context. // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for details.
IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL);
IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context
IMGUI_API ImGuiContext* GetCurrentContext(); IMGUI_API ImGuiContext* GetCurrentContext();
@ -868,9 +871,11 @@ namespace ImGui
IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro.
// Memory Allocators // Memory Allocators
// - All those functions are not reliant on the current context. // - Those functions are not reliant on the current context.
// - If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again because we use global storage for those. // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL); // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
IMGUI_API void SetAllocatorFunctions(ImGuiMemAllocFunc* alloc_func, ImGuiMemFreeFunc* free_func, void* user_data = NULL);
IMGUI_API void GetAllocatorFunctions(ImGuiMemAllocFunc** p_alloc_func, ImGuiMemFreeFunc** p_free_func, void** p_user_data);
IMGUI_API void* MemAlloc(size_t size); IMGUI_API void* MemAlloc(size_t size);
IMGUI_API void MemFree(void* ptr); IMGUI_API void MemFree(void* ptr);