diff options
author | Ignacio Roldán Etcheverry <ignalfonsore@gmail.com> | 2021-12-28 23:25:16 +0100 |
---|---|---|
committer | Ignacio Roldán Etcheverry <ignalfonsore@gmail.com> | 2022-08-22 03:36:51 +0200 |
commit | 88e367a4066773a6fbfe2ea25dc2e81d2035d791 (patch) | |
tree | a219a4332cb7b4c05daacce718af76347774df77 /modules/mono/mono_gd | |
parent | f88d8902cfc0d6a9441e794eb47611ef4ed0d46c (diff) |
C#/netcore: Add base desktop game export implementation
This base implementation is still very barebones but it defines the path
for how exporting will work (at least when embedding the .NET runtime).
Many manual steps are still needed, which should be automatized in the
future. For example, in addition to the API assemblies, now you also
need to copy the GodotPlugins assembly to each game project.
Diffstat (limited to 'modules/mono/mono_gd')
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 268 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.h | 44 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_cache.cpp | 2 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_cache.h | 6 |
4 files changed, 257 insertions, 63 deletions
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 7a3fd1af10..0792a88f52 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -42,7 +42,9 @@ #include "../utils/path_utils.h" #include "gd_mono_cache.h" +#ifdef TOOLS_ENABLED #include <nethost.h> +#endif #include <coreclr_delegates.h> #include <hostfxr.h> @@ -129,6 +131,7 @@ void gd_mono_debug_init() { } // namespace namespace { +hostfxr_initialize_for_dotnet_command_line_fn hostfxr_initialize_for_dotnet_command_line = nullptr; hostfxr_initialize_for_runtime_config_fn hostfxr_initialize_for_runtime_config = nullptr; hostfxr_get_runtime_delegate_fn hostfxr_get_runtime_delegate = nullptr; hostfxr_close_fn hostfxr_close = nullptr; @@ -151,6 +154,7 @@ HostFxrCharString str_to_hostfxr(const String &p_str) { #endif } +#ifdef TOOLS_ENABLED String str_from_hostfxr(const char_t *p_buffer) { #ifdef _WIN32 return String::utf16((const char16_t *)p_buffer); @@ -158,36 +162,98 @@ String str_from_hostfxr(const char_t *p_buffer) { return String::utf8((const char *)p_buffer); #endif } +#endif const char_t *get_data(const HostFxrCharString &p_char_str) { return (const char_t *)p_char_str.get_data(); } +#ifdef TOOLS_ENABLED +String find_hostfxr(size_t p_known_buffet_size, get_hostfxr_parameters *p_get_hostfxr_params) { + // Pre-allocate a large buffer for the path to hostfxr + Vector<char_t> buffer; + buffer.resize(p_known_buffet_size); + + int rc = get_hostfxr_path(buffer.ptrw(), &p_known_buffet_size, p_get_hostfxr_params); + + ERR_FAIL_COND_V_MSG(rc != 0, String(), "get_hostfxr_path failed with code: " + itos(rc)); + + return str_from_hostfxr(buffer.ptr()); +} +#endif + String find_hostfxr() { +#ifdef TOOLS_ENABLED + const int CoreHostLibMissingFailure = 0x80008083; const int HostApiBufferTooSmall = 0x80008098; size_t buffer_size = 0; int rc = get_hostfxr_path(nullptr, &buffer_size, nullptr); if (rc == HostApiBufferTooSmall) { - // Pre-allocate a large buffer for the path to hostfxr - Vector<char_t> buffer; - buffer.resize(buffer_size); - - rc = get_hostfxr_path(buffer.ptrw(), &buffer_size, nullptr); + return find_hostfxr(buffer_size, nullptr); + } - if (rc != 0) { - return String(); + if (rc == CoreHostLibMissingFailure) { + // Apparently `get_hostfxr_path` doesn't look for dotnet in `PATH`? (I suppose it needs the + // `DOTNET_ROOT` environment variable). If it fails, we try to find the dotnet executable + // in `PATH` ourselves and pass its location as `dotnet_root` to `get_hostfxr_path`. + String dotnet_exe = path::find_executable("dotnet"); + + if (!dotnet_exe.is_empty()) { + // The file found in PATH may be a symlink + dotnet_exe = path::abspath(path::realpath(dotnet_exe)); + + // TODO: + // Sometimes, the symlink may not point to the dotnet executable in the dotnet root. + // That's the case with snaps. The snap install should have been found with the + // previous `get_hostfxr_path`, but it would still be better to do this properly + // and use something like `dotnet --list-sdks/runtimes` to find the actual location. + // This way we could also check if the proper sdk or runtime is installed. This would + // allow us to fail gracefully and show some helpful information in the editor. + + HostFxrCharString dotnet_root = str_to_hostfxr(dotnet_exe.get_base_dir()); + + get_hostfxr_parameters get_hostfxr_parameters = { + sizeof(get_hostfxr_parameters), + nullptr, + get_data(dotnet_root) + }; + + buffer_size = 0; + rc = get_hostfxr_path(nullptr, &buffer_size, &get_hostfxr_parameters); + if (rc == HostApiBufferTooSmall) { + return find_hostfxr(buffer_size, &get_hostfxr_parameters); + } } + } - return str_from_hostfxr(buffer.ptr()); + if (rc == CoreHostLibMissingFailure) { + ERR_PRINT(String() + ".NET: One of the dependent libraries is missing. " + + "Typically when the `hostfxr`, `hostpolicy` or `coreclr` dynamic " + + "libraries are not present in the expected locations."); } return String(); +#else + +#if defined(WINDOWS_ENABLED) + return GodotSharpDirs::get_api_assemblies_dir() + .plus_file("hostfxr.dll"); +#elif defined(MACOS_ENABLED) + return GodotSharpDirs::get_api_assemblies_dir() + .plus_file("libhostfxr.dylib"); +#elif defined(UNIX_ENABLED) + return GodotSharpDirs::get_api_assemblies_dir() + .plus_file("libhostfxr.so"); +#else +#error "Platform not supported (yet?)" +#endif + +#endif } -// Forward declarations -bool load_hostfxr() { +bool load_hostfxr(void *&r_hostfxr_dll_handle) { String hostfxr_path = find_hostfxr(); if (hostfxr_path.is_empty()) { @@ -196,16 +262,20 @@ bool load_hostfxr() { print_verbose("Found hostfxr: " + hostfxr_path); - void *lib = nullptr; - Error err = OS::get_singleton()->open_dynamic_library(hostfxr_path, lib); - // TODO: Clean up lib handle when shutting down + Error err = OS::get_singleton()->open_dynamic_library(hostfxr_path, r_hostfxr_dll_handle); if (err != OK) { return false; } + void *lib = r_hostfxr_dll_handle; + void *symbol = nullptr; + err = OS::get_singleton()->get_dynamic_library_symbol_handle(lib, "hostfxr_initialize_for_dotnet_command_line", symbol); + ERR_FAIL_COND_V(err != OK, false); + hostfxr_initialize_for_dotnet_command_line = (hostfxr_initialize_for_dotnet_command_line_fn)symbol; + err = OS::get_singleton()->get_dynamic_library_symbol_handle(lib, "hostfxr_initialize_for_runtime_config", symbol); ERR_FAIL_COND_V(err != OK, false); hostfxr_initialize_for_runtime_config = (hostfxr_initialize_for_runtime_config_fn)symbol; @@ -223,12 +293,13 @@ bool load_hostfxr() { hostfxr_close); } -load_assembly_and_get_function_pointer_fn initialize_hostfxr(const char_t *p_config_path) { +#ifdef TOOLS_ENABLED +load_assembly_and_get_function_pointer_fn initialize_hostfxr_for_config(const char_t *p_config_path) { hostfxr_handle cxt = nullptr; int rc = hostfxr_initialize_for_runtime_config(p_config_path, nullptr, &cxt); if (rc != 0 || cxt == nullptr) { hostfxr_close(cxt); - ERR_FAIL_V_MSG(nullptr, "hostfxr_initialize_for_runtime_config failed"); + ERR_FAIL_V_MSG(nullptr, "hostfxr_initialize_for_runtime_config failed with code: " + itos(rc)); } void *load_assembly_and_get_function_pointer = nullptr; @@ -236,13 +307,122 @@ load_assembly_and_get_function_pointer_fn initialize_hostfxr(const char_t *p_con rc = hostfxr_get_runtime_delegate(cxt, hdt_load_assembly_and_get_function_pointer, &load_assembly_and_get_function_pointer); if (rc != 0 || load_assembly_and_get_function_pointer == nullptr) { - ERR_FAIL_V_MSG(nullptr, "hostfxr_get_runtime_delegate failed"); + ERR_FAIL_V_MSG(nullptr, "hostfxr_get_runtime_delegate failed with code: " + itos(rc)); } hostfxr_close(cxt); return (load_assembly_and_get_function_pointer_fn)load_assembly_and_get_function_pointer; } +#else +load_assembly_and_get_function_pointer_fn initialize_hostfxr_self_contained( + const char_t *p_main_assembly_path) { + hostfxr_handle cxt = nullptr; + + List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); + + List<HostFxrCharString> argv_store; + Vector<const char_t *> argv; + argv.resize(cmdline_args.size() + 1); + + argv.write[0] = p_main_assembly_path; + + int i = 1; + for (const String &E : cmdline_args) { + HostFxrCharString &stored = argv_store.push_back(str_to_hostfxr(E))->get(); + argv.write[i] = stored.ptr(); + i++; + } + + int rc = hostfxr_initialize_for_dotnet_command_line(argv.size(), argv.ptrw(), nullptr, &cxt); + if (rc != 0 || cxt == nullptr) { + hostfxr_close(cxt); + ERR_FAIL_V_MSG(nullptr, "hostfxr_initialize_for_dotnet_command_line failed with code: " + itos(rc)); + } + + void *load_assembly_and_get_function_pointer = nullptr; + + rc = hostfxr_get_runtime_delegate(cxt, + hdt_load_assembly_and_get_function_pointer, &load_assembly_and_get_function_pointer); + if (rc != 0 || load_assembly_and_get_function_pointer == nullptr) { + ERR_FAIL_V_MSG(nullptr, "hostfxr_get_runtime_delegate failed with code: " + itos(rc)); + } + + hostfxr_close(cxt); + + return (load_assembly_and_get_function_pointer_fn)load_assembly_and_get_function_pointer; +} +#endif + +#ifdef TOOLS_ENABLED +using godot_plugins_initialize_fn = bool (*)(bool, gdmono::PluginCallbacks *, GDMonoCache::ManagedCallbacks *); +#else +using godot_plugins_initialize_fn = bool (*)(GDMonoCache::ManagedCallbacks *); +#endif + +#ifdef TOOLS_ENABLED +godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) { + godot_plugins_initialize_fn godot_plugins_initialize = nullptr; + + HostFxrCharString godot_plugins_path = str_to_hostfxr( + GodotSharpDirs::get_api_assemblies_dir().plus_file("GodotPlugins.dll")); + + HostFxrCharString config_path = str_to_hostfxr( + GodotSharpDirs::get_api_assemblies_dir().plus_file("GodotPlugins.runtimeconfig.json")); + + load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer = + initialize_hostfxr_for_config(get_data(config_path)); + ERR_FAIL_NULL_V(load_assembly_and_get_function_pointer, nullptr); + + r_runtime_initialized = true; + + print_verbose(".NET: hostfxr initialized"); + + int rc = load_assembly_and_get_function_pointer(get_data(godot_plugins_path), + HOSTFXR_STR("GodotPlugins.Main, GodotPlugins"), + HOSTFXR_STR("InitializeFromEngine"), + UNMANAGEDCALLERSONLY_METHOD, + nullptr, + (void **)&godot_plugins_initialize); + ERR_FAIL_COND_V_MSG(rc != 0, nullptr, ".NET: Failed to get GodotPlugins initialization function pointer"); + + return godot_plugins_initialize; +} +#else +godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) { + String appname = ProjectSettings::get_singleton()->get("application/config/name"); + String appname_safe = OS::get_singleton()->get_safe_dir_name(appname); + if (appname_safe.is_empty()) { + appname_safe = "UnnamedProject"; + } + + godot_plugins_initialize_fn godot_plugins_initialize = nullptr; + + String assembly_name = appname_safe; + + HostFxrCharString assembly_path = str_to_hostfxr(GodotSharpDirs::get_api_assemblies_dir() + .plus_file(assembly_name + ".dll")); + + load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer = + initialize_hostfxr_self_contained(get_data(assembly_path)); + ERR_FAIL_NULL_V(load_assembly_and_get_function_pointer, nullptr); + + r_runtime_initialized = true; + + print_verbose(".NET: hostfxr initialized"); + + int rc = load_assembly_and_get_function_pointer(get_data(assembly_path), + str_to_hostfxr("GodotPlugins.Game.Main, " + assembly_name), + HOSTFXR_STR("InitializeFromGameProject"), + UNMANAGEDCALLERSONLY_METHOD, + nullptr, + (void **)&godot_plugins_initialize); + ERR_FAIL_COND_V_MSG(rc != 0, nullptr, ".NET: Failed to get GodotPlugins initialization function pointer"); + + return godot_plugins_initialize; +} +#endif + } // namespace static bool _on_core_api_assembly_loaded() { @@ -261,61 +441,44 @@ static bool _on_core_api_assembly_loaded() { } void GDMono::initialize() { - ERR_FAIL_NULL(Engine::get_singleton()); - print_verbose(".NET: Initializing module..."); _init_godot_api_hashes(); - if (!load_hostfxr()) { + if (!load_hostfxr(hostfxr_dll_handle)) { ERR_FAIL_MSG(".NET: Failed to load hostfxr"); } - auto config_path = str_to_hostfxr(GodotSharpDirs::get_api_assemblies_dir() - .plus_file("GodotPlugins.runtimeconfig.json")); - - load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer = - initialize_hostfxr(get_data(config_path)); - ERR_FAIL_NULL(load_assembly_and_get_function_pointer); - - runtime_initialized = true; - - print_verbose(".NET: hostfxr initialized"); - - auto godot_plugins_path = str_to_hostfxr(GodotSharpDirs::get_api_assemblies_dir() - .plus_file("GodotPlugins.dll")); - - using godot_plugins_initialize_fn = bool (*)(bool, PluginCallbacks *, GDMonoCache::ManagedCallbacks *); - godot_plugins_initialize_fn godot_plugins_initialize = nullptr; - - int rc = load_assembly_and_get_function_pointer(get_data(godot_plugins_path), - HOSTFXR_STR("GodotPlugins.Main, GodotPlugins"), - HOSTFXR_STR("Initialize"), - UNMANAGEDCALLERSONLY_METHOD, - nullptr, - (void **)&godot_plugins_initialize); - ERR_FAIL_COND_MSG(rc != 0, ".NET: Failed to get Godot.Plugins Initialize function pointer"); + godot_plugins_initialize_fn godot_plugins_initialize = + initialize_hostfxr_and_godot_plugins(runtime_initialized); + ERR_FAIL_NULL(godot_plugins_initialize); - PluginCallbacks aux_plugin_callbacks; GDMonoCache::ManagedCallbacks managed_callbacks; + +#ifdef TOOLS_ENABLED + gdmono::PluginCallbacks plugin_callbacks_res; bool init_ok = godot_plugins_initialize(Engine::get_singleton()->is_editor_hint(), - &aux_plugin_callbacks, &managed_callbacks); - ERR_FAIL_COND_MSG(!init_ok, ".NET: Call to Godot.Plugins Initialize failed"); + &plugin_callbacks_res, &managed_callbacks); + ERR_FAIL_COND_MSG(!init_ok, ".NET: GodotPlugins initialization failed"); + + plugin_callbacks = plugin_callbacks_res; +#else + bool init_ok = godot_plugins_initialize(&managed_callbacks); + ERR_FAIL_COND_MSG(!init_ok, ".NET: GodotPlugins initialization failed"); +#endif GDMonoCache::update_godot_api_cache(managed_callbacks); - plugin_callbacks = aux_plugin_callbacks; print_verbose(".NET: GodotPlugins initialized"); _on_core_api_assembly_loaded(); } +#ifdef TOOLS_ENABLED void GDMono::initialize_load_assemblies() { -#if defined(TOOLS_ENABLED) if (Engine::get_singleton()->is_project_manager_hint()) { return; } -#endif // Load the project's main assembly. This doesn't necessarily need to succeed. // The game may not be using .NET at all, or if the project does use .NET and @@ -326,6 +489,7 @@ void GDMono::initialize_load_assemblies() { } } } +#endif void GDMono::_init_godot_api_hashes() { #ifdef DEBUG_METHODS_ENABLED @@ -337,6 +501,7 @@ void GDMono::_init_godot_api_hashes() { #endif // DEBUG_METHODS_ENABLED } +#ifdef TOOLS_ENABLED bool GDMono::_load_project_assembly() { String appname = ProjectSettings::get_singleton()->get("application/config/name"); String appname_safe = OS::get_singleton()->get_safe_dir_name(appname); @@ -350,6 +515,7 @@ bool GDMono::_load_project_assembly() { return plugin_callbacks.LoadProjectAssemblyCallback(assembly_path.utf16()); } +#endif #warning TODO hot-reload #if 0 @@ -479,6 +645,10 @@ GDMono::~GDMono() { } } + if (hostfxr_dll_handle) { + OS::get_singleton()->close_dynamic_library(hostfxr_dll_handle); + } + finalizing_scripts_domain = false; runtime_initialized = false; diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index fee1cab9c7..66ed331b67 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -35,11 +35,36 @@ #include "../godotsharp_defs.h" +#ifdef WIN32 +#define GD_CLR_STDCALL __stdcall +#else +#define GD_CLR_STDCALL +#endif + +namespace gdmono { + +#ifdef TOOLS_ENABLED +struct PluginCallbacks { + using FuncLoadProjectAssemblyCallback = bool(GD_CLR_STDCALL *)(const char16_t *); + using FuncLoadToolsAssemblyCallback = Object *(GD_CLR_STDCALL *)(const char16_t *); + FuncLoadProjectAssemblyCallback LoadProjectAssemblyCallback = nullptr; + FuncLoadToolsAssemblyCallback LoadToolsAssemblyCallback = nullptr; +}; +#endif + +} // namespace gdmono + +#undef GD_CLR_STDCALL + class GDMono { bool runtime_initialized; bool finalizing_scripts_domain; + void *hostfxr_dll_handle = nullptr; + +#ifdef TOOLS_ENABLED bool _load_project_assembly(); +#endif bool _try_load_api_assemblies(); @@ -51,18 +76,9 @@ class GDMono { #endif void _init_godot_api_hashes(); - friend class CSharpLanguage; -#ifdef WIN32 -#define GD_CLR_STDCALL __stdcall -#else -#define GD_CLR_STDCALL +#ifdef TOOLS_ENABLED + gdmono::PluginCallbacks plugin_callbacks; #endif - struct PluginCallbacks { - using FuncLoadProjectAssemblyCallback = bool(GD_CLR_STDCALL *)(const char16_t *); - using FuncLoadToolsAssemblyCallback = Object *(GD_CLR_STDCALL *)(const char16_t *); - FuncLoadProjectAssemblyCallback LoadProjectAssemblyCallback = nullptr; - FuncLoadToolsAssemblyCallback LoadToolsAssemblyCallback = nullptr; - } plugin_callbacks; protected: static GDMono *singleton; @@ -102,12 +118,18 @@ public: _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized; } _FORCE_INLINE_ bool is_finalizing_scripts_domain() { return finalizing_scripts_domain; } +#ifdef TOOLS_ENABLED + const gdmono::PluginCallbacks &get_plugin_callbacks() { return plugin_callbacks; } +#endif + #ifdef GD_MONO_HOT_RELOAD Error reload_scripts_domain(); #endif void initialize(); +#ifdef TOOLS_ENABLED void initialize_load_assemblies(); +#endif GDMono(); ~GDMono(); diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index e8b25cb119..7d33f0a896 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -54,7 +54,6 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) { CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, RaiseEventSignal); CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetScriptSignalList); CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, HasScriptSignal); - CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, HasMethodUnknownParams); CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, ScriptIsOrInherits); CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, AddScriptBridge); CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, RemoveScriptBridge); @@ -65,6 +64,7 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) { CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Get); CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, CallDispose); CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, CallToString); + CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, HasMethodUnknownParams); CHECK_CALLBACK_NOT_NULL(GCHandleBridge, FreeGCHandle); CHECK_CALLBACK_NOT_NULL(DebuggingUtils, InstallTraceListener); CHECK_CALLBACK_NOT_NULL(Dispatcher, InitializeDefaultGodotTaskScheduler); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 17c8c9fa51..b993facff9 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -64,7 +64,6 @@ struct ManagedCallbacks { using FuncScriptManagerBridge_RaiseEventSignal = void(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, const Variant **, int, bool *); using FuncScriptManagerBridge_GetScriptSignalList = void(GD_CLR_STDCALL *)(const CSharpScript *, Dictionary *); using FuncScriptManagerBridge_HasScriptSignal = bool(GD_CLR_STDCALL *)(const CSharpScript *, const String *); - using FuncScriptManagerBridge_HasMethodUnknownParams = bool(GD_CLR_STDCALL *)(const CSharpScript *, const String *, bool); using FuncScriptManagerBridge_ScriptIsOrInherits = bool(GD_CLR_STDCALL *)(const CSharpScript *, const CSharpScript *); using FuncScriptManagerBridge_AddScriptBridge = bool(GD_CLR_STDCALL *)(const CSharpScript *, const String *); using FuncScriptManagerBridge_RemoveScriptBridge = void(GD_CLR_STDCALL *)(const CSharpScript *); @@ -75,6 +74,7 @@ struct ManagedCallbacks { using FuncCSharpInstanceBridge_Get = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, Variant *); using FuncCSharpInstanceBridge_CallDispose = void(GD_CLR_STDCALL *)(GCHandleIntPtr, bool); using FuncCSharpInstanceBridge_CallToString = void(GD_CLR_STDCALL *)(GCHandleIntPtr, String *, bool *); + using FuncCSharpInstanceBridge_HasMethodUnknownParams = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *); using FuncGCHandleBridge_FreeGCHandle = void(GD_CLR_STDCALL *)(GCHandleIntPtr); using FuncDebuggingUtils_InstallTraceListener = void(GD_CLR_STDCALL *)(); using FuncDispatcher_InitializeDefaultGodotTaskScheduler = void(GD_CLR_STDCALL *)(); @@ -91,7 +91,6 @@ struct ManagedCallbacks { FuncScriptManagerBridge_RaiseEventSignal ScriptManagerBridge_RaiseEventSignal; FuncScriptManagerBridge_GetScriptSignalList ScriptManagerBridge_GetScriptSignalList; FuncScriptManagerBridge_HasScriptSignal ScriptManagerBridge_HasScriptSignal; - FuncScriptManagerBridge_HasMethodUnknownParams ScriptManagerBridge_HasMethodUnknownParams; FuncScriptManagerBridge_ScriptIsOrInherits ScriptManagerBridge_ScriptIsOrInherits; FuncScriptManagerBridge_AddScriptBridge ScriptManagerBridge_AddScriptBridge; FuncScriptManagerBridge_RemoveScriptBridge ScriptManagerBridge_RemoveScriptBridge; @@ -102,6 +101,7 @@ struct ManagedCallbacks { FuncCSharpInstanceBridge_Get CSharpInstanceBridge_Get; FuncCSharpInstanceBridge_CallDispose CSharpInstanceBridge_CallDispose; FuncCSharpInstanceBridge_CallToString CSharpInstanceBridge_CallToString; + FuncCSharpInstanceBridge_HasMethodUnknownParams CSharpInstanceBridge_HasMethodUnknownParams; FuncGCHandleBridge_FreeGCHandle GCHandleBridge_FreeGCHandle; FuncDebuggingUtils_InstallTraceListener DebuggingUtils_InstallTraceListener; FuncDispatcher_InitializeDefaultGodotTaskScheduler Dispatcher_InitializeDefaultGodotTaskScheduler; @@ -118,4 +118,6 @@ inline void clear_godot_api_cache() { } } // namespace GDMonoCache +#undef GD_CLR_STDCALL + #endif // GD_MONO_CACHE_H |