From c5a88ac5e304fddbd86f7b8c799a43963002f839 Mon Sep 17 00:00:00 2001 From: Atdunbg <979541498@qq.com> Date: Sun, 26 Oct 2025 16:08:38 +0800 Subject: [PATCH] add c# debugging support --- Editor/src/Editor/EditorLayer.cpp | 2 +- Hazel/src/Hazel/Scripting/ScriptEngine.cpp | 49 ++++++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/Editor/src/Editor/EditorLayer.cpp b/Editor/src/Editor/EditorLayer.cpp index 314eebd..6aa58e0 100644 --- a/Editor/src/Editor/EditorLayer.cpp +++ b/Editor/src/Editor/EditorLayer.cpp @@ -320,7 +320,7 @@ namespace Hazel static float fpsRefreshTime = 0.0f; static float displayedFPS = 0; - float currentTime = ImGui::GetTime(); + float currentTime = static_cast(ImGui::GetTime()); // 每秒更新一次要显示的FPS if (currentTime - fpsRefreshTime >= 1.0f) diff --git a/Hazel/src/Hazel/Scripting/ScriptEngine.cpp b/Hazel/src/Hazel/Scripting/ScriptEngine.cpp index cf42ed2..8838436 100644 --- a/Hazel/src/Hazel/Scripting/ScriptEngine.cpp +++ b/Hazel/src/Hazel/Scripting/ScriptEngine.cpp @@ -13,6 +13,8 @@ #include "mono/jit/jit.h" #include "mono/metadata/assembly.h" #include "mono/metadata/attrdefs.h" +#include "mono/metadata/mono-debug.h" +#include "mono/metadata/threads.h" namespace Hazel { @@ -72,7 +74,7 @@ namespace Hazel return buffer; } - MonoAssembly* LoadMonoAssembly(const std::filesystem::path& assemblyPath) + MonoAssembly* LoadMonoAssembly(const std::filesystem::path& assemblyPath, bool loadPDB = false) { HZ_CORE_DEBUG("Load Assemble: {0}", assemblyPath.string().c_str()); uint32_t fileSize = 0; @@ -88,6 +90,24 @@ namespace Hazel return nullptr; } + if (loadPDB) + { + HZ_CORE_INFO("loading pdb file..."); + std::filesystem::path pdbPath(assemblyPath); + pdbPath.replace_extension(".pdb"); + + if (std::filesystem::exists(pdbPath)) + { + uint32_t pdbFileSize = 0; + char* pdbFileData = ReadBytes(pdbPath, &pdbFileSize); + mono_debug_open_image_from_memory(image, (const mono_byte*)pdbFileData, fileSize); + HZ_CORE_INFO("loaded pdb file: {0}", pdbPath.string()); + HZ_CORE_INFO(" size: {0}", pdbFileSize); + + delete[] pdbFileData; + } + } + std::string string = assemblyPath.string(); MonoAssembly* assembly = mono_assembly_load_from_full(image, string.c_str(), &status, 0); mono_image_close(image); @@ -152,6 +172,9 @@ namespace Hazel Scope> AppAssemblyFileWatcher; bool AssemblyReloading = false; + // Mono C# debug + bool EnableDebugging = true; + // runtime Scene* SceneContext = nullptr; }; @@ -235,7 +258,7 @@ namespace Hazel // TODO: move this later s_Data->CoreAssemblyFilePath = assemblePath; - s_Data->CoreAssembly = Utils::LoadMonoAssembly(assemblePath); + s_Data->CoreAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); s_Data->CoreAssemblyImage = mono_assembly_get_image(s_Data->CoreAssembly); // Utils::PrintAssemblyTypes(s_Data->CoreAssembly); @@ -245,7 +268,7 @@ namespace Hazel { // TODO: move this later s_Data->AppAssemblyFilePath = assemblePath; - s_Data->AppAssembly = Utils::LoadMonoAssembly(assemblePath); + s_Data->AppAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); s_Data->AppAssemblyImage = mono_assembly_get_image(s_Data->AppAssembly); s_Data->AppAssemblyFileWatcher = CreateScope>(assemblePath.string(), OnAssemblyFileSystemEvent); @@ -408,6 +431,18 @@ namespace Hazel mono_set_dirs("Resources", "Resources"); mono_set_assemblies_path("Resources/mono"); + if (s_Data->EnableDebugging) + { + const char* argv[2] + { + "--debugger-agent=transport=dt_socket,address=127.0.0.1:2550,server=y,suspend=n,loglevel=3,logfile=MonoDebugger.log", + "--soft-breakpoints" + }; + + mono_jit_parse_options(2, (char**)argv); + mono_debug_init(MONO_DEBUG_FORMAT_MONO); + } + MonoDomain* rootDomain = mono_jit_init("HazelJITRuntime"); const char* monoPath = mono_assembly_getrootdir(); @@ -419,6 +454,11 @@ namespace Hazel } // Storage the root Domain ptr s_Data->RootDomain = rootDomain; + + if (s_Data->EnableDebugging) + mono_debug_domain_create(s_Data->RootDomain); + + mono_thread_set_main(mono_thread_current()); } void ScriptEngine::MonoShutdown() @@ -468,7 +508,8 @@ namespace Hazel MonoObject* ScriptClass::InvokeMethod(MonoObject* instance, MonoMethod* method, void** param) { - return mono_runtime_invoke(method, instance, param, nullptr); + MonoObject* expection = nullptr; + return mono_runtime_invoke(method, instance, param, &expection); }