From 842a9d9075a08211eab4e265ea05ad98a41d6ad2 Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Mon, 5 Oct 2026 00:58:06 +0800 Subject: [PATCH 1/5] Optimize activation factory using binary search --- cppwinrt/component_writers.h | 129 ++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 47 deletions(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 94e20e53e..1f3f41fe5 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -76,14 +76,7 @@ namespace cppwinrt return; } - if (settings.component_opt) - { - auto format = R"(void* winrt_make_%(); -)"; - - w.write(format, get_impl_name(type.TypeNamespace(), type.TypeName())); - } - else + if (!settings.component_opt) { auto format = R"(#include "%.h" )"; @@ -105,42 +98,86 @@ namespace cppwinrt if (settings.component_opt) { - auto format = R"( - if (requal(name, L"%.%")) - { - return winrt_make_%(); - } + auto format = R"(void* winrt_make_%(); )"; - w.write(format, - type_namespace, - type_name, - impl_name); + w.write(format, impl_name); } else { - auto format = R"( - if (requal(name, L"%.%")) - { - return winrt::detach_abi(winrt::make()); - } + auto format = R"(void* winrt_make_%() +{ + return winrt::detach_abi(winrt::make()); +} )"; w.write(format, - type_namespace, - type_name, + impl_name, type_namespace, type_name); } } + static void add_component_manifest_entry(writer& w, TypeDef const& type, std::vector& manifest) + { + if (!has_factory_members(w, type) || is_always_disabled(type)) + { + return; + } + + std::string name; + name += type.TypeNamespace(); + name += '.'; + name += type.TypeName(); + manifest.push_back(std::move(name)); + } + static void write_module_g_cpp(writer& w, std::vector const& classes) { if (!settings.modules) { w.write_root_include("base"); } - auto format = R"(% + + for (auto&& type : classes) + { + write_component_include(w, type); + } + + std::vector manifest; + + for (auto&& type : classes) + { + add_component_manifest_entry(w, type, manifest); + } + + // Sort the strings so that binary search can be used. + std::sort(manifest.begin(), manifest.end()); + + w.write("#define WINRT_ACTIVATION_TABLE(X)\\\n"); + + for (std::size_t i = 0; i + 1 < manifest.size(); ++i) + { + w.write(std::string{ " X(winrt_make_" } + get_impl_name(manifest[i]) + ", L\"" + manifest[i] + "\") \\\n"); + } + + if (!manifest.empty()) + { + w.write(std::string{ " X(winrt_make_" } + get_impl_name(manifest.back()) + ", L\"" + manifest.back() + "\")\n"); + } + + auto declarations = R"( +#define WINRT_DECLARE_FUNC(func, name) void* func(); +WINRT_ACTIVATION_TABLE(WINRT_DECLARE_FUNC) +)"; + w.write(declarations); + + for (auto&& type : classes) + { + write_component_activation(w, type); + } + + auto format = R"( bool __stdcall %_can_unload_now() noexcept { if (winrt::get_module_lock()) @@ -154,20 +191,31 @@ bool __stdcall %_can_unload_now() noexcept void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view const& name) { - auto requal = [](std::wstring_view const& left, std::wstring_view const& right) noexcept +#if % + static constexpr std::wstring_view names[] = { - return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend()); +#define WINRT_NAME_LIST(func, name) name, + WINRT_ACTIVATION_TABLE(WINRT_NAME_LIST) }; -% + + using make_t = void* (*)(); + static constexpr make_t makes[] = + { +#define WINRT_MAKE_LIST(func, name) func, + WINRT_ACTIVATION_TABLE(WINRT_MAKE_LIST) + }; + + auto it = std::lower_bound(std::begin(names), std::end(names), name); + if (it != std::end(names) && *it == name) + { + return makes[it - std::begin(names)](); + } +#endif return nullptr; } )"; - w.write(format, - bind_each(classes), - settings.component_lib, - settings.component_lib, - bind_each(classes)); + w.write(format, settings.component_lib, settings.component_lib, manifest.empty() ? 0 : 1); if (settings.component_lib != "winrt") { @@ -379,21 +427,8 @@ catch (...) { return winrt::to_hresult(); } { auto type_name = type.TypeName(); auto type_namespace = type.TypeNamespace(); - auto impl_name = get_impl_name(type_namespace, type_name); - - if (has_factory_members(w, type)) - { - auto format = R"(void* winrt_make_%() -{ - return winrt::detach_abi(winrt::make()); -} -)"; - w.write(format, - impl_name, - type_namespace, - type_name); - } + write_component_activation(w, type); if (!settings.component_opt) { From 100d5fefd913564b66ae0482cf4b74487a83578d Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Mon, 5 Oct 2026 01:16:06 +0800 Subject: [PATCH 2/5] Fix CI --- cppwinrt/component_writers.h | 37 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 1f3f41fe5..2699f7425 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -85,7 +85,7 @@ namespace cppwinrt } } - static void write_component_activation(writer& w, TypeDef const& type) + static void write_component_make_definition(writer& w, TypeDef const& type) { if (!has_factory_members(w, type) || is_always_disabled(type)) { @@ -96,25 +96,38 @@ namespace cppwinrt auto type_namespace = type.TypeNamespace(); auto impl_name = get_impl_name(type_namespace, type_name); + auto format = R"(void* winrt_make_%() +{ + return winrt::detach_abi(winrt::make()); +} +)"; + + w.write(format, + impl_name, + type_namespace, + type_name); + } + + static void write_component_activation(writer& w, TypeDef const& type) + { + if (!has_factory_members(w, type) || is_always_disabled(type)) + { + return; + } + + auto impl_name = get_impl_name(type.TypeNamespace(), type.TypeName()); + if (settings.component_opt) { auto format = R"(void* winrt_make_%(); )"; w.write(format, impl_name); + return; } else { - auto format = R"(void* winrt_make_%() -{ - return winrt::detach_abi(winrt::make()); -} -)"; - - w.write(format, - impl_name, - type_namespace, - type_name); + write_component_make_definition(w, type); } } @@ -428,7 +441,7 @@ catch (...) { return winrt::to_hresult(); } auto type_name = type.TypeName(); auto type_namespace = type.TypeNamespace(); - write_component_activation(w, type); + write_component_make_definition(w, type); if (!settings.component_opt) { From 64dbcdd4e32ea17e6223359ddaae05976788ad3b Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Mon, 5 Oct 2026 02:22:00 +0800 Subject: [PATCH 3/5] Remove redundant function declarations --- cppwinrt/component_writers.h | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 2699f7425..b0c90d8bb 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -110,25 +110,11 @@ namespace cppwinrt static void write_component_activation(writer& w, TypeDef const& type) { - if (!has_factory_members(w, type) || is_always_disabled(type)) - { - return; - } - - auto impl_name = get_impl_name(type.TypeNamespace(), type.TypeName()); - - if (settings.component_opt) - { - auto format = R"(void* winrt_make_%(); -)"; - - w.write(format, impl_name); - return; - } - else + if (!settings.component_opt) { write_component_make_definition(w, type); } + // Declarations are synthesized by WINRT_DECLARE_FUNC to avoid duplication } static void add_component_manifest_entry(writer& w, TypeDef const& type, std::vector& manifest) From 0a8e13667a66e4490abbbab00d190d5305e15329 Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Mon, 5 Oct 2026 03:42:59 +0800 Subject: [PATCH 4/5] Simplify code --- cppwinrt/component_writers.h | 53 ++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index b0c90d8bb..f6083e32f 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -108,16 +108,26 @@ namespace cppwinrt type_name); } - static void write_component_activation(writer& w, TypeDef const& type) + static void write_component_activation(writer& w, std::vector const& classes) { if (!settings.component_opt) { - write_component_make_definition(w, type); + for (auto&& type : classes) + { + write_component_make_definition(w, type); + } + } + else + { + auto declarations = R"( +#define WINRT_DECLARE_FUNC(func, name) void* func(); +WINRT_ACTIVATION_TABLE(WINRT_DECLARE_FUNC) +)"; + w.write(declarations); } - // Declarations are synthesized by WINRT_DECLARE_FUNC to avoid duplication } - static void add_component_manifest_entry(writer& w, TypeDef const& type, std::vector& manifest) + static void collect_component(writer& w, TypeDef const& type, std::vector& components) { if (!has_factory_members(w, type) || is_always_disabled(type)) { @@ -128,7 +138,7 @@ namespace cppwinrt name += type.TypeNamespace(); name += '.'; name += type.TypeName(); - manifest.push_back(std::move(name)); + components.push_back(std::move(name)); } static void write_module_g_cpp(writer& w, std::vector const& classes) @@ -138,43 +148,28 @@ namespace cppwinrt w.write_root_include("base"); } + std::vector components; for (auto&& type : classes) { write_component_include(w, type); - } - - std::vector manifest; - - for (auto&& type : classes) - { - add_component_manifest_entry(w, type, manifest); + collect_component(w, type, components); } // Sort the strings so that binary search can be used. - std::sort(manifest.begin(), manifest.end()); - + std::sort(components.begin(), components.end()); w.write("#define WINRT_ACTIVATION_TABLE(X)\\\n"); - for (std::size_t i = 0; i + 1 < manifest.size(); ++i) + for (std::size_t i = 0; i + 1 < components.size(); ++i) { - w.write(std::string{ " X(winrt_make_" } + get_impl_name(manifest[i]) + ", L\"" + manifest[i] + "\") \\\n"); + w.write(std::string{ " X(winrt_make_" } + get_impl_name(components[i]) + ", L\"" + components[i] + "\") \\\n"); } - if (!manifest.empty()) + if (!components.empty()) { - w.write(std::string{ " X(winrt_make_" } + get_impl_name(manifest.back()) + ", L\"" + manifest.back() + "\")\n"); + w.write(std::string{ " X(winrt_make_" } + get_impl_name(components.back()) + ", L\"" + components.back() + "\")\n"); } - auto declarations = R"( -#define WINRT_DECLARE_FUNC(func, name) void* func(); -WINRT_ACTIVATION_TABLE(WINRT_DECLARE_FUNC) -)"; - w.write(declarations); - - for (auto&& type : classes) - { - write_component_activation(w, type); - } + write_component_activation(w, classes); auto format = R"( bool __stdcall %_can_unload_now() noexcept @@ -214,7 +209,7 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons } )"; - w.write(format, settings.component_lib, settings.component_lib, manifest.empty() ? 0 : 1); + w.write(format, settings.component_lib, settings.component_lib, components.empty() ? 0 : 1); if (settings.component_lib != "winrt") { From 3caa8cbf66eacec05c629117e0d63b90a4e59e30 Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Tue, 6 Oct 2026 07:49:30 +0800 Subject: [PATCH 5/5] Use std::find when the number of classes is le_eq to 32 --- cppwinrt/component_writers.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index f6083e32f..aa664569a 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -199,8 +199,13 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons WINRT_ACTIVATION_TABLE(WINRT_MAKE_LIST) }; +#if % <= 32 + auto it = std::find(std::begin(names), std::end(names), name); + if (it != std::end(names)) +#else auto it = std::lower_bound(std::begin(names), std::end(names), name); if (it != std::end(names) && *it == name) +#endif { return makes[it - std::begin(names)](); } @@ -209,7 +214,7 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons } )"; - w.write(format, settings.component_lib, settings.component_lib, components.empty() ? 0 : 1); + w.write(format, settings.component_lib, settings.component_lib, components.size(), components.size()); if (settings.component_lib != "winrt") {