summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2021-09-12 19:50:13 +0200
committerIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2022-08-22 03:35:59 +0200
commit5e37d073bb86492e8c415964ffd554a2fa08920d (patch)
tree1023544131f8117ac5b61d12bdc6b6f790513429 /modules
parent9a51430441eecafbd07a7b9eb46967e2c3dd8b5d (diff)
C#: Re-write GD and some other icalls as P/Invoke
Diffstat (limited to 'modules')
-rw-r--r--modules/mono/csharp_script.cpp21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs200
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs14
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs84
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/ScriptManager.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj1
-rw-r--r--modules/mono/glue/base_object_glue.cpp36
-rw-r--r--modules/mono/glue/gd_glue.cpp342
-rw-r--r--modules/mono/glue/runtime_interop.cpp214
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp18
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h3
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp57
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h9
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp10
19 files changed, 442 insertions, 635 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 9520598f5c..4316f38bd2 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -109,7 +109,7 @@ Error CSharpLanguage::execute_file(const String &p_path) {
return OK;
}
-extern void *godotsharp_pinvoke_funcs[138];
+extern void *godotsharp_pinvoke_funcs[164];
[[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
void CSharpLanguage::init() {
@@ -705,19 +705,14 @@ void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) {
void CSharpLanguage::frame() {
if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != nullptr) {
- const Ref<MonoGCHandleRef> &task_scheduler_handle = GDMonoCache::cached_data.task_scheduler_handle;
-
- if (task_scheduler_handle.is_valid()) {
- MonoObject *task_scheduler = task_scheduler_handle->get_target();
-
- if (task_scheduler) {
- MonoException *exc = nullptr;
- CACHED_METHOD_THUNK(GodotTaskScheduler, Activate).invoke(task_scheduler, &exc);
+ MonoException *exc = nullptr;
+ gdmono->get_core_api_assembly()
+ ->get_class("Godot", "ScriptManager")
+ ->get_method("FrameCallback")
+ ->invoke(nullptr, &exc);
- if (exc) {
- GDMonoUtils::debug_unhandled_exception(exc);
- }
- }
+ if (exc) {
+ GDMonoUtils::debug_unhandled_exception(exc);
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
index 6475237002..5f84bb530f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs
@@ -1,20 +1,14 @@
-using System.Runtime.CompilerServices;
-
namespace Godot
{
public static class Dispatcher
{
- /// <summary>
- /// Implements an external instance of GodotTaskScheduler.
- /// </summary>
- /// <returns>A GodotTaskScheduler instance.</returns>
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern GodotTaskScheduler godot_icall_DefaultGodotTaskScheduler();
+ internal static GodotTaskScheduler DefaultGodotTaskScheduler;
+
+ private static void InitializeDefaultGodotTaskScheduler()
+ {
+ DefaultGodotTaskScheduler = new GodotTaskScheduler();
+ }
- /// <summary>
- /// Initializes the synchronization context as the context of the GodotTaskScheduler.
- /// </summary>
- public static GodotSynchronizationContext SynchronizationContext =>
- godot_icall_DefaultGodotTaskScheduler().Context;
+ public static GodotSynchronizationContext SynchronizationContext => DefaultGodotTaskScheduler.Context;
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
index 691fd85964..340780bb45 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
@@ -1,5 +1,5 @@
using System;
-using System.Runtime.CompilerServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -32,10 +32,20 @@ namespace Godot
/// </returns>
public static WeakRef WeakRef(Object obj)
{
- return godot_icall_Object_weakref(GetPtr(obj));
- }
+ if (!IsInstanceValid(obj))
+ return null;
+
+ using godot_ref weakRef = default;
+
+ unsafe
+ {
+ NativeFuncs.godotsharp_weakref(GetPtr(obj), &weakRef);
+ }
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern WeakRef godot_icall_Object_weakref(IntPtr obj);
+ if (weakRef.IsNull)
+ return null;
+
+ return (WeakRef)InteropUtils.UnmanagedGetManaged(weakRef._reference);
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index e8ea8f379b..9d237b8d93 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -5,7 +5,6 @@ using real_t = System.Single;
#endif
using System;
using System.Collections.Generic;
-using System.Runtime.CompilerServices;
using Godot.NativeInterop;
namespace Godot
@@ -30,7 +29,9 @@ namespace Godot
public static unsafe object Bytes2Var(byte[] bytes, bool allowObjects = false)
{
using var varBytes = Marshaling.mono_array_to_PackedByteArray(bytes);
- return godot_icall_GD_bytes2var(&varBytes, allowObjects);
+ using godot_variant ret = default;
+ NativeFuncs.godotsharp_bytes2var(&varBytes, allowObjects, &ret);
+ return Marshaling.variant_to_mono_object(&ret);
}
/// <summary>
@@ -48,9 +49,12 @@ namespace Godot
/// </code>
/// </example>
/// <returns>The <c>Variant</c> converted to the given <paramref name="type"/>.</returns>
- public static object Convert(object what, Variant.Type type)
+ public static unsafe object Convert(object what, Variant.Type type)
{
- return godot_icall_GD_convert(what, type);
+ using var whatVariant = Marshaling.mono_object_to_variant(what);
+ using godot_variant ret = default;
+ NativeFuncs.godotsharp_convert(&whatVariant, (int)type, &ret);
+ return Marshaling.variant_to_mono_object(&ret);
}
/// <summary>
@@ -64,7 +68,7 @@ namespace Godot
return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
}
- private static object[] GetPrintParams(object[] parameters)
+ private static string[] GetPrintParams(object[] parameters)
{
if (parameters == null)
{
@@ -84,9 +88,10 @@ namespace Godot
/// </example>
/// <param name="var">Variable that will be hashed.</param>
/// <returns>Hash of the variable passed.</returns>
- public static int Hash(object var)
+ public static unsafe int Hash(object var)
{
- return godot_icall_GD_hash(var);
+ using var variant = Marshaling.mono_object_to_variant(var);
+ return NativeFuncs.godotsharp_hash(&variant);
}
/// <summary>
@@ -112,7 +117,7 @@ namespace Godot
/// <returns>The <see cref="Object"/> instance.</returns>
public static Object InstanceFromId(ulong instanceId)
{
- return godot_icall_GD_instance_from_id(instanceId);
+ return InteropUtils.UnmanagedGetManaged(NativeFuncs.godotsharp_instance_from_id(instanceId));
}
/// <summary>
@@ -202,9 +207,10 @@ namespace Godot
/// </code>
/// </example>
/// <param name="message">Error message.</param>
- public static void PushError(string message)
+ public static unsafe void PushError(string message)
{
- godot_icall_GD_pusherror(message);
+ using var godotStr = Marshaling.mono_string_to_godot(message);
+ NativeFuncs.godotsharp_pusherror(&godotStr);
}
/// <summary>
@@ -214,9 +220,10 @@ namespace Godot
/// GD.PushWarning("test warning"); // Prints "test warning" to debugger and terminal as warning call
/// </example>
/// <param name="message">Warning message.</param>
- public static void PushWarning(string message)
+ public static unsafe void PushWarning(string message)
{
- godot_icall_GD_pushwarning(message);
+ using var godotStr = Marshaling.mono_string_to_godot(message);
+ NativeFuncs.godotsharp_pushwarning(&godotStr);
}
/// <summary>
@@ -235,9 +242,11 @@ namespace Godot
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
- public static void Print(params object[] what)
+ public static unsafe void Print(params object[] what)
{
- godot_icall_GD_print(GetPrintParams(what));
+ string str = string.Concat(GetPrintParams(what));
+ using var godotStr = Marshaling.mono_string_to_godot(str);
+ NativeFuncs.godotsharp_print(&godotStr);
}
/// <summary>
@@ -264,9 +273,11 @@ namespace Godot
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
- public static void PrintRich(params object[] what)
+ public static unsafe void PrintRich(params object[] what)
{
- godot_icall_GD_print_rich(GetPrintParams(what));
+ string str = string.Concat(GetPrintParams(what));
+ using var godotStr = Marshaling.mono_string_to_godot(str);
+ NativeFuncs.godotsharp_print_rich(&godotStr);
}
/// <summary>
@@ -286,9 +297,11 @@ namespace Godot
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
- public static void PrintErr(params object[] what)
+ public static unsafe void PrintErr(params object[] what)
{
- godot_icall_GD_printerr(GetPrintParams(what));
+ string str = string.Concat(GetPrintParams(what));
+ using var godotStr = Marshaling.mono_string_to_godot(str);
+ NativeFuncs.godotsharp_printerr(&godotStr);
}
/// <summary>
@@ -306,9 +319,11 @@ namespace Godot
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
- public static void PrintRaw(params object[] what)
+ public static unsafe void PrintRaw(params object[] what)
{
- godot_icall_GD_printraw(GetPrintParams(what));
+ string str = string.Concat(GetPrintParams(what));
+ using var godotStr = Marshaling.mono_string_to_godot(str);
+ NativeFuncs.godotsharp_printraw(&godotStr);
}
/// <summary>
@@ -320,9 +335,11 @@ namespace Godot
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
- public static void PrintS(params object[] what)
+ public static unsafe void PrintS(params object[] what)
{
- godot_icall_GD_prints(GetPrintParams(what));
+ string str = string.Join(' ', GetPrintParams(what));
+ using var godotStr = Marshaling.mono_string_to_godot(str);
+ NativeFuncs.godotsharp_prints(&godotStr);
}
/// <summary>
@@ -334,9 +351,11 @@ namespace Godot
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
- public static void PrintT(params object[] what)
+ public static unsafe void PrintT(params object[] what)
{
- godot_icall_GD_printt(GetPrintParams(what));
+ string str = string.Join('\t', GetPrintParams(what));
+ using var godotStr = Marshaling.mono_string_to_godot(str);
+ NativeFuncs.godotsharp_printt(&godotStr);
}
/// <summary>
@@ -350,7 +369,7 @@ namespace Godot
/// <returns>A random <see langword="float"/> number.</returns>
public static float Randf()
{
- return godot_icall_GD_randf();
+ return NativeFuncs.godotsharp_randf();
}
/// <summary>
@@ -360,7 +379,7 @@ namespace Godot
/// <returns>A random normally-distributed <see langword="float"/> number.</returns>
public static double Randfn(double mean, double deviation)
{
- return godot_icall_GD_randfn(mean, deviation);
+ return NativeFuncs.godotsharp_randfn(mean, deviation);
}
/// <summary>
@@ -378,7 +397,7 @@ namespace Godot
/// <returns>A random <see langword="uint"/> number.</returns>
public static uint Randi()
{
- return godot_icall_GD_randi();
+ return NativeFuncs.godotsharp_randi();
}
/// <summary>
@@ -391,7 +410,7 @@ namespace Godot
/// </summary>
public static void Randomize()
{
- godot_icall_GD_randomize();
+ NativeFuncs.godotsharp_randomize();
}
/// <summary>
@@ -406,7 +425,7 @@ namespace Godot
/// <returns>A random <see langword="double"/> number inside the given range.</returns>
public static double RandRange(double from, double to)
{
- return godot_icall_GD_randf_range(from, to);
+ return NativeFuncs.godotsharp_randf_range(from, to);
}
/// <summary>
@@ -423,7 +442,7 @@ namespace Godot
/// <returns>A random <see langword="int"/> number inside the given range.</returns>
public static int RandRange(int from, int to)
{
- return godot_icall_GD_randi_range(from, to);
+ return NativeFuncs.godotsharp_randi_range(from, to);
}
/// <summary>
@@ -436,7 +455,7 @@ namespace Godot
/// <returns>A random <see langword="uint"/> number.</returns>
public static uint RandFromSeed(ref ulong seed)
{
- return godot_icall_GD_rand_seed(seed, out seed);
+ return NativeFuncs.godotsharp_rand_from_seed(seed, out seed);
}
/// <summary>
@@ -493,7 +512,7 @@ namespace Godot
/// <param name="seed">Seed that will be used.</param>
public static void Seed(ulong seed)
{
- godot_icall_GD_seed(seed);
+ NativeFuncs.godotsharp_seed(seed);
}
/// <summary>
@@ -501,9 +520,12 @@ namespace Godot
/// </summary>
/// <param name="what">Arguments that will converted to string.</param>
/// <returns>The string formed by the given arguments.</returns>
- public static string Str(params object[] what)
+ public static unsafe string Str(params object[] what)
{
- return godot_icall_GD_str(what);
+ using var whatGodotArray = Marshaling.mono_array_to_Array(what);
+ using godot_string ret = default;
+ NativeFuncs.godotsharp_str(&whatGodotArray, &ret);
+ return Marshaling.mono_string_from_godot(&ret);
}
/// <summary>
@@ -518,18 +540,12 @@ namespace Godot
/// </example>
/// <param name="str">String that will be converted to Variant.</param>
/// <returns>The decoded <c>Variant</c>.</returns>
- public static object Str2Var(string str)
+ public static unsafe object Str2Var(string str)
{
- return godot_icall_GD_str2var(str);
- }
-
- /// <summary>
- /// Returns whether the given class exists in <see cref="ClassDB"/>.
- /// </summary>
- /// <returns>If the class exists in <see cref="ClassDB"/>.</returns>
- public static bool TypeExists(StringName type)
- {
- return godot_icall_GD_type_exists(ref type.NativeValue);
+ using var godotStr = Marshaling.mono_string_to_godot(str);
+ using godot_variant ret = default;
+ NativeFuncs.godotsharp_str2var(&godotStr, &ret);
+ return Marshaling.variant_to_mono_object(&ret);
}
/// <summary>
@@ -543,12 +559,11 @@ namespace Godot
/// <returns>The <c>Variant</c> encoded as an array of bytes.</returns>
public static unsafe byte[] Var2Bytes(object var, bool fullObjects = false)
{
- godot_packed_byte_array varBytes;
- godot_icall_GD_var2bytes(var, fullObjects, &varBytes);
+ using var variant = Marshaling.mono_object_to_variant(var);
+ using godot_packed_byte_array varBytes = default;
+ NativeFuncs.godotsharp_var2bytes(&variant, fullObjects, &varBytes);
using (varBytes)
- {
return Marshaling.PackedByteArray_to_mono_array(&varBytes);
- }
}
/// <summary>
@@ -568,9 +583,12 @@ namespace Godot
/// </example>
/// <param name="var">Variant that will be converted to string.</param>
/// <returns>The <c>Variant</c> encoded as a string.</returns>
- public static string Var2Str(object var)
+ public static unsafe string Var2Str(object var)
{
- return godot_icall_GD_var2str(var);
+ using var variant = Marshaling.mono_object_to_variant(var);
+ using godot_string ret = default;
+ NativeFuncs.godotsharp_var2str(&variant, &ret);
+ return Marshaling.mono_string_from_godot(&ret);
}
/// <summary>
@@ -579,85 +597,7 @@ namespace Godot
/// <returns>The <see cref="Variant.Type"/> for the given <paramref name="type"/>.</returns>
public static Variant.Type TypeToVariantType(Type type)
{
- return godot_icall_TypeToVariantType(type);
+ return Marshaling.managed_to_variant_type(type, out bool _);
}
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern unsafe object godot_icall_GD_bytes2var(godot_packed_byte_array* bytes, bool allowObjects);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object godot_icall_GD_convert(object what, Variant.Type type);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_GD_hash(object var);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern Object godot_icall_GD_instance_from_id(ulong instanceId);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_print(object[] what);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_print_rich(object[] what);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_printerr(object[] what);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_printraw(object[] what);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_prints(object[] what);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_printt(object[] what);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_randomize();
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern uint godot_icall_GD_randi();
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern float godot_icall_GD_randf();
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_GD_randi_range(int from, int to);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern double godot_icall_GD_randf_range(double from, double to);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern double godot_icall_GD_randfn(double mean, double deviation);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_seed(ulong seed);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern string godot_icall_GD_str(object[] what);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object godot_icall_GD_str2var(string str);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_GD_type_exists(ref godot_string_name type);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern unsafe void godot_icall_GD_var2bytes(object what, bool fullObjects, godot_packed_byte_array* bytes);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern string godot_icall_GD_var2str(object var);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_pusherror(string type);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_GD_pushwarning(string type);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern Variant.Type godot_icall_TypeToVariantType(Type type);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
index ddcb6b9091..865863cd3e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
@@ -36,6 +36,8 @@ namespace Godot.NativeInterop
NativeFuncs.godotsharp_ref_destroy(ref this);
_reference = IntPtr.Zero;
}
+
+ public bool IsNull => _reference == IntPtr.Zero;
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index 590fb082e8..e0819b2857 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -18,8 +18,10 @@ namespace Godot.NativeInterop
fieldInfo.SetValue(obj, valueObj);
}
- public static Variant.Type managed_to_variant_type(Type type, ref bool r_nil_is_variant)
+ public static Variant.Type managed_to_variant_type(Type type, out bool r_nil_is_variant)
{
+ r_nil_is_variant = false;
+
switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
@@ -199,8 +201,6 @@ namespace Godot.NativeInterop
}
}
- r_nil_is_variant = false;
-
// Unknown
return Variant.Type.Nil;
}
@@ -711,7 +711,7 @@ namespace Godot.NativeInterop
if (typeof(Godot.Object[]).IsAssignableFrom(type))
{
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return Array_to_mono_array_of_type(&godotArray, type);
+ return Array_to_mono_array_of_godot_object_type(&godotArray, type);
}
if (type == typeof(object[]))
@@ -1136,7 +1136,7 @@ namespace Godot.NativeInterop
return ret;
}
- public static unsafe object Array_to_mono_array_of_type(godot_array* p_array, Type type)
+ public static unsafe object Array_to_mono_array_of_godot_object_type(godot_array* p_array, Type type)
{
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_array_new_copy(p_array));
@@ -1144,7 +1144,9 @@ namespace Godot.NativeInterop
int length = array.Count;
object ret = Activator.CreateInstance(type, length);
- array.CopyTo((object[])ret, 0); // variant_to_mono_object handled by Collections.Array
+ // variant_to_mono_object handled by Collections.Array
+ // variant_to_mono_object_of_type is not needed because target element types are Godot.Object (or derived)
+ array.CopyTo((object[])ret, 0);
return ret;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
index 0680ec7be5..adbf5eb9b6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
@@ -510,5 +510,89 @@ namespace Godot.NativeInterop
[DllImport(GodotDllName)]
public static extern bool godotsharp_node_path_is_absolute(ref godot_node_path p_self);
+
+ // GD, etc
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_bytes2var(godot_packed_byte_array* p_bytes, bool p_allow_objects,
+ godot_variant* r_ret);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_convert(godot_variant* p_what, int p_type, godot_variant* r_ret);
+
+ [DllImport(GodotDllName)]
+ public static extern int godotsharp_hash(godot_variant* var);
+
+ [DllImport(GodotDllName)]
+ public static extern IntPtr godotsharp_instance_from_id(ulong instanceId);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_print(godot_string* p_what);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_print_rich(godot_string* p_what);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_printerr(godot_string* p_what);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_printraw(godot_string* p_what);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_prints(godot_string* p_what);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_printt(godot_string* p_what);
+
+ [DllImport(GodotDllName)]
+ public static extern float godotsharp_randf();
+
+ [DllImport(GodotDllName)]
+ public static extern uint godotsharp_randi();
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_randomize();
+
+ [DllImport(GodotDllName)]
+ public static extern double godotsharp_randf_range(double from, double to);
+
+ [DllImport(GodotDllName)]
+ public static extern double godotsharp_randfn(double mean, double deviation);
+
+ [DllImport(GodotDllName)]
+ public static extern int godotsharp_randi_range(int from, int to);
+
+ [DllImport(GodotDllName)]
+ public static extern uint godotsharp_rand_from_seed(ulong seed, out ulong newSeed);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_seed(ulong seed);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_weakref(IntPtr obj, godot_ref* r_weak_ref);
+
+ [DllImport(GodotDllName)]
+ public static extern string godotsharp_str(godot_array* p_what, godot_string* r_ret);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_str2var(godot_string* p_str, godot_variant* r_ret);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_var2bytes(godot_variant* what, bool fullObjects,
+ godot_packed_byte_array* bytes);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_var2str(godot_variant* var, godot_string* r_ret);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_pusherror(godot_string* type);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_pushwarning(godot_string* type);
+
+ // Object
+
+ [DllImport(GodotDllName)]
+ public static extern string godotsharp_object_to_string(IntPtr ptr, godot_string* r_str);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
index 9c4265517e..7bbaef62fa 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.CompilerServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -101,9 +102,11 @@ namespace Godot
/// Converts this <see cref="Object"/> to a string.
/// </summary>
/// <returns>A string representation of this object.</returns>
- public override string ToString()
+ public override unsafe string ToString()
{
- return godot_icall_Object_ToString(GetPtr(this));
+ using godot_string str = default;
+ NativeFuncs.godotsharp_object_to_string(GetPtr(this), &str);
+ return Marshaling.mono_string_from_godot(&str);
}
/// <summary>
@@ -190,8 +193,5 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void godot_icall_Object_ConnectEventSignals(IntPtr obj);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern string godot_icall_Object_ToString(IntPtr ptr);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/ScriptManager.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/ScriptManager.cs
new file mode 100644
index 0000000000..e92688f5bb
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/ScriptManager.cs
@@ -0,0 +1,10 @@
+namespace Godot
+{
+ internal class ScriptManager
+ {
+ internal static void FrameCallback()
+ {
+ Dispatcher.DefaultGodotTaskScheduler?.Activate();
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 0709723da0..36faf92144 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -71,6 +71,7 @@
<Compile Include="Core\NativeInterop\NativeFuncs.cs" />
<Compile Include="Core\NativeInterop\InteropStructs.cs" />
<Compile Include="Core\NativeInterop\Marshaling.cs" />
+ <Compile Include="Core\ScriptManager.cs" />
<Compile Include="Core\SignalInfo.cs" />
<Compile Include="Core\SignalAwaiter.cs" />
<Compile Include="Core\StringExtensions.cs" />
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index c252ee47f4..d56b70e739 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -124,50 +124,14 @@ void godot_icall_Object_ConnectEventSignals(Object *p_ptr) {
}
}
-MonoObject *godot_icall_Object_weakref(Object *p_ptr) {
- if (!p_ptr) {
- return nullptr;
- }
-
- Ref<WeakRef> wref;
- RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
-
- if (rc) {
- Ref<RefCounted> r = rc;
- if (!r.is_valid()) {
- return nullptr;
- }
-
- wref.instantiate();
- wref->set_ref(r);
- } else {
- wref.instantiate();
- wref->set_obj(p_ptr);
- }
-
- return GDMonoUtils::unmanaged_get_managed(wref.ptr());
-}
-
int32_t godot_icall_SignalAwaiter_connect(Object *p_source, StringName *p_signal, Object *p_target, MonoObject *p_awaiter) {
StringName signal = p_signal ? *p_signal : StringName();
return (int32_t)gd_mono_connect_signal_awaiter(p_source, signal, p_target, p_awaiter);
}
-MonoString *godot_icall_Object_ToString(Object *p_ptr) {
-#ifdef DEBUG_ENABLED
- // Cannot happen in C#; would get an ObjectDisposedException instead.
- CRASH_COND(p_ptr == nullptr);
-#endif
- // Can't call 'Object::to_string()' here, as that can end up calling 'ToString' again resulting in an endless circular loop.
- String result = "[" + p_ptr->get_class() + ":" + itos(p_ptr->get_instance_id()) + "]";
- return GDMonoMarshal::mono_string_from_godot(result);
-}
-
void godot_register_object_icalls() {
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Disposed", godot_icall_Object_Disposed);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_RefCounted_Disposed", godot_icall_RefCounted_Disposed);
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ConnectEventSignals", godot_icall_Object_ConnectEventSignals);
- GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ToString", godot_icall_Object_ToString);
- GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_weakref", godot_icall_Object_weakref);
GDMonoUtils::add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", godot_icall_SignalAwaiter_connect);
}
diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp
deleted file mode 100644
index b315831819..0000000000
--- a/modules/mono/glue/gd_glue.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/*************************************************************************/
-/* gd_glue.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "core/io/marshalls.h"
-#include "core/os/os.h"
-#include "core/string/ustring.h"
-#include "core/variant/array.h"
-#include "core/variant/variant.h"
-#include "core/variant/variant_parser.h"
-
-#include "../mono_gd/gd_mono_cache.h"
-#include "../mono_gd/gd_mono_marshal.h"
-#include "../mono_gd/gd_mono_utils.h"
-
-MonoObject *godot_icall_GD_bytes2var(PackedByteArray *p_bytes, MonoBoolean p_allow_objects) {
- Variant ret;
- Error err = decode_variant(ret, p_bytes->ptr(), p_bytes->size(), nullptr, p_allow_objects);
- if (err != OK) {
- ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
- }
- return GDMonoMarshal::variant_to_mono_object(ret);
-}
-
-MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type) {
- Variant what = GDMonoMarshal::mono_object_to_variant(p_what);
- const Variant *args[1] = { &what };
- Callable::CallError ce;
- Variant ret;
- Variant::construct(Variant::Type(p_type), ret, args, 1, ce);
- ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
- return GDMonoMarshal::variant_to_mono_object(ret);
-}
-
-int godot_icall_GD_hash(MonoObject *p_var) {
- return GDMonoMarshal::mono_object_to_variant(p_var).hash();
-}
-
-MonoObject *godot_icall_GD_instance_from_id(uint64_t p_instance_id) {
- return GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(ObjectID(p_instance_id)));
-}
-
-void godot_icall_GD_print(MonoArray *p_what) {
- String str;
- int length = mono_array_length(p_what);
-
- for (int i = 0; i < length; i++) {
- MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
-
- MonoException *exc = nullptr;
- String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
-
- if (exc) {
- GDMonoUtils::set_pending_exception(exc);
- return;
- }
-
- str += elem_str;
- }
-
- print_line(str);
-}
-
-void godot_icall_GD_print_rich(MonoArray *p_what) {
- String str;
- int length = mono_array_length(p_what);
-
- for (int i = 0; i < length; i++) {
- MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
-
- MonoException *exc = nullptr;
- String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
-
- if (exc) {
- GDMonoUtils::set_pending_exception(exc);
- return;
- }
-
- str += elem_str;
- }
-
- print_line_rich(str);
-}
-
-void godot_icall_GD_printerr(MonoArray *p_what) {
- String str;
- int length = mono_array_length(p_what);
-
- for (int i = 0; i < length; i++) {
- MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
-
- MonoException *exc = nullptr;
- String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
-
- if (exc) {
- GDMonoUtils::set_pending_exception(exc);
- return;
- }
-
- str += elem_str;
- }
-
- print_error(str);
-}
-
-void godot_icall_GD_printraw(MonoArray *p_what) {
- String str;
- int length = mono_array_length(p_what);
-
- for (int i = 0; i < length; i++) {
- MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
-
- MonoException *exc = nullptr;
- String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
-
- if (exc) {
- GDMonoUtils::set_pending_exception(exc);
- return;
- }
-
- str += elem_str;
- }
-
- OS::get_singleton()->print("%s", str.utf8().get_data());
-}
-
-void godot_icall_GD_prints(MonoArray *p_what) {
- String str;
- int length = mono_array_length(p_what);
-
- for (int i = 0; i < length; i++) {
- MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
-
- MonoException *exc = nullptr;
- String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
-
- if (exc) {
- GDMonoUtils::set_pending_exception(exc);
- return;
- }
-
- if (i) {
- str += " ";
- }
-
- str += elem_str;
- }
-
- print_line(str);
-}
-
-void godot_icall_GD_printt(MonoArray *p_what) {
- String str;
- int length = mono_array_length(p_what);
-
- for (int i = 0; i < length; i++) {
- MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
-
- MonoException *exc = nullptr;
- String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
-
- if (exc) {
- GDMonoUtils::set_pending_exception(exc);
- return;
- }
-
- if (i) {
- str += "\t";
- }
-
- str += elem_str;
- }
-
- print_line(str);
-}
-
-void godot_icall_GD_randomize() {
- Math::randomize();
-}
-
-uint32_t godot_icall_GD_randi() {
- return Math::rand();
-}
-
-float godot_icall_GD_randf() {
- return Math::randf();
-}
-
-int32_t godot_icall_GD_randi_range(int32_t from, int32_t to) {
- return Math::random(from, to);
-}
-
-double godot_icall_GD_randf_range(double from, double to) {
- return Math::random(from, to);
-}
-
-double godot_icall_GD_randfn(double mean, double deviation) {
- return Math::randfn(mean, deviation);
-}
-
-uint32_t godot_icall_GD_rand_seed(uint64_t seed, uint64_t *newSeed) {
- uint32_t ret = Math::rand_from_seed(&seed);
- *newSeed = seed;
- return ret;
-}
-
-void godot_icall_GD_seed(uint64_t p_seed) {
- Math::seed(p_seed);
-}
-
-MonoString *godot_icall_GD_str(MonoArray *p_what) {
- String str;
- Array what = GDMonoMarshal::mono_array_to_Array(p_what);
-
- for (int i = 0; i < what.size(); i++) {
- String os = what[i].operator String();
-
- if (i == 0) {
- str = os;
- } else {
- str += os;
- }
- }
-
- return GDMonoMarshal::mono_string_from_godot(str);
-}
-
-MonoObject *godot_icall_GD_str2var(MonoString *p_str) {
- Variant ret;
-
- VariantParser::StreamString ss;
- ss.s = GDMonoMarshal::mono_string_to_godot(p_str);
-
- String errs;
- int line;
- Error err = VariantParser::parse(&ss, ret, errs, line);
- if (err != OK) {
- String err_str = "Parse error at line " + itos(line) + ": " + errs + ".";
- ERR_PRINT(err_str);
- ret = err_str;
- }
-
- return GDMonoMarshal::variant_to_mono_object(ret);
-}
-
-MonoBoolean godot_icall_GD_type_exists(StringName *p_type) {
- StringName type = p_type ? *p_type : StringName();
- return ClassDB::class_exists(type);
-}
-
-void godot_icall_GD_pusherror(MonoString *p_str) {
- ERR_PRINT(GDMonoMarshal::mono_string_to_godot(p_str));
-}
-
-void godot_icall_GD_pushwarning(MonoString *p_str) {
- WARN_PRINT(GDMonoMarshal::mono_string_to_godot(p_str));
-}
-
-void godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects, PackedByteArray *r_bytes) {
- memnew_placement(r_bytes, PackedByteArray);
-
- Variant var = GDMonoMarshal::mono_object_to_variant(p_var);
-
- int len;
- Error err = encode_variant(var, nullptr, len, p_full_objects);
- ERR_FAIL_COND_MSG(err != OK, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
-
- r_bytes->resize(len);
- encode_variant(var, r_bytes->ptrw(), len, p_full_objects);
-}
-
-MonoString *godot_icall_GD_var2str(MonoObject *p_var) {
- String vars;
- VariantWriter::write_to_string(GDMonoMarshal::mono_object_to_variant(p_var), vars);
- return GDMonoMarshal::mono_string_from_godot(vars);
-}
-
-uint32_t godot_icall_TypeToVariantType(MonoReflectionType *p_refl_type) {
- return (uint32_t)GDMonoMarshal::managed_to_variant_type(ManagedType::from_reftype(p_refl_type));
-}
-
-MonoObject *godot_icall_DefaultGodotTaskScheduler() {
- return GDMonoCache::cached_data.task_scheduler_handle->get_target();
-}
-
-void godot_register_gd_icalls() {
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_bytes2var", godot_icall_GD_bytes2var);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_convert", godot_icall_GD_convert);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_hash", godot_icall_GD_hash);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_instance_from_id", godot_icall_GD_instance_from_id);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pusherror", godot_icall_GD_pusherror);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pushwarning", godot_icall_GD_pushwarning);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print", godot_icall_GD_print);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print_rich", godot_icall_GD_print_rich);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printerr", godot_icall_GD_printerr);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printraw", godot_icall_GD_printraw);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_prints", godot_icall_GD_prints);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printt", godot_icall_GD_printt);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randomize", godot_icall_GD_randomize);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi", godot_icall_GD_randi);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf", godot_icall_GD_randf);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi_range", godot_icall_GD_randi_range);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf_range", godot_icall_GD_randf_range);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randfn", godot_icall_GD_randfn);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_rand_seed", godot_icall_GD_rand_seed);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_seed", godot_icall_GD_seed);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_str", godot_icall_GD_str);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_str2var", godot_icall_GD_str2var);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_type_exists", godot_icall_GD_type_exists);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_var2bytes", godot_icall_GD_var2bytes);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_var2str", godot_icall_GD_var2str);
- GDMonoUtils::add_internal_call("Godot.GD::godot_icall_TypeToVariantType", godot_icall_TypeToVariantType);
-
- // Dispatcher
- GDMonoUtils::add_internal_call("Godot.Dispatcher::godot_icall_DefaultGodotTaskScheduler", godot_icall_DefaultGodotTaskScheduler);
-}
diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp
index f5a04bf05c..2860386127 100644
--- a/modules/mono/glue/runtime_interop.cpp
+++ b/modules/mono/glue/runtime_interop.cpp
@@ -29,8 +29,10 @@
/*************************************************************************/
#include "core/config/engine.h"
+#include "core/io/marshalls.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
+#include "core/os/os.h"
#include "core/string/string_name.h"
#include "../interop_types.h"
@@ -839,12 +841,194 @@ GD_PINVOKE_EXPORT bool godotsharp_node_path_is_absolute(const NodePath *p_self)
return p_self->is_absolute();
}
+GD_PINVOKE_EXPORT void godotsharp_randomize() {
+ Math::randomize();
+}
+
+GD_PINVOKE_EXPORT uint32_t godotsharp_randi() {
+ return Math::rand();
+}
+
+GD_PINVOKE_EXPORT float godotsharp_randf() {
+ return Math::randf();
+}
+
+GD_PINVOKE_EXPORT int32_t godotsharp_randi_range(int32_t p_from, int32_t p_to) {
+ return Math::random(p_from, p_to);
+}
+
+GD_PINVOKE_EXPORT double godotsharp_randf_range(double p_from, double p_to) {
+ return Math::random(p_from, p_to);
+}
+
+GD_PINVOKE_EXPORT double godotsharp_randfn(double p_mean, double p_deviation) {
+ return Math::randfn(p_mean, p_deviation);
+}
+
+GD_PINVOKE_EXPORT void godotsharp_seed(uint64_t p_seed) {
+ Math::seed(p_seed);
+}
+
+GD_PINVOKE_EXPORT uint32_t godotsharp_rand_from_seed(uint64_t p_seed, uint64_t *r_new_seed) {
+ uint32_t ret = Math::rand_from_seed(&p_seed);
+ *r_new_seed = p_seed;
+ return ret;
+}
+
+GD_PINVOKE_EXPORT void godotsharp_weakref(Object *p_ptr, Ref<RefCounted> *r_weak_ref) {
+ if (!p_ptr) {
+ return;
+ }
+
+ Ref<WeakRef> wref;
+ RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
+
+ if (rc) {
+ Ref<RefCounted> r = rc;
+ if (!r.is_valid()) {
+ return;
+ }
+
+ wref.instantiate();
+ wref->set_ref(r);
+ } else {
+ wref.instantiate();
+ wref->set_obj(p_ptr);
+ }
+
+ memnew_placement(r_weak_ref, Ref<RefCounted>(wref));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_str(const godot_array *p_what, godot_string *r_ret) {
+ String &str = *memnew_placement(r_ret, String);
+ const Array &what = *reinterpret_cast<const Array *>(p_what);
+
+ for (int i = 0; i < what.size(); i++) {
+ String os = what[i].operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+}
+
+GD_PINVOKE_EXPORT void godotsharp_print(const godot_string *p_what) {
+ print_line(*reinterpret_cast<const String *>(p_what));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_print_rich(const godot_string *p_what) {
+ print_line_rich(*reinterpret_cast<const String *>(p_what));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_printerr(const godot_string *p_what) {
+ print_error(*reinterpret_cast<const String *>(p_what));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_printt(const godot_string *p_what) {
+ print_line(*reinterpret_cast<const String *>(p_what));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_prints(const godot_string *p_what) {
+ print_line(*reinterpret_cast<const String *>(p_what));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_printraw(const godot_string *p_what) {
+ OS::get_singleton()->print("%s", reinterpret_cast<const String *>(p_what)->utf8().get_data());
+}
+
+GD_PINVOKE_EXPORT void godotsharp_pusherror(const godot_string *p_str) {
+ ERR_PRINT(*reinterpret_cast<const String *>(p_str));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_pushwarning(const godot_string *p_str) {
+ WARN_PRINT(*reinterpret_cast<const String *>(p_str));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_var2str(const godot_variant *p_var, godot_string *r_ret) {
+ const Variant &var = *reinterpret_cast<const Variant *>(p_var);
+ String &vars = *memnew_placement(r_ret, String);
+ VariantWriter::write_to_string(var, vars);
+}
+
+GD_PINVOKE_EXPORT void godotsharp_str2var(const godot_string *p_str, godot_variant *r_ret) {
+ Variant ret;
+
+ VariantParser::StreamString ss;
+ ss.s = *reinterpret_cast<const String *>(p_str);
+
+ String errs;
+ int line;
+ Error err = VariantParser::parse(&ss, ret, errs, line);
+ if (err != OK) {
+ String err_str = "Parse error at line " + itos(line) + ": " + errs + ".";
+ ERR_PRINT(err_str);
+ ret = err_str;
+ }
+ memnew_placement(r_ret, Variant(ret));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_var2bytes(const godot_variant *p_var, bool p_full_objects, godot_packed_array *r_bytes) {
+ const Variant &var = *reinterpret_cast<const Variant *>(p_var);
+ PackedByteArray &bytes = *memnew_placement(r_bytes, PackedByteArray);
+
+ int len;
+ Error err = encode_variant(var, nullptr, len, p_full_objects);
+ ERR_FAIL_COND_MSG(err != OK, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
+
+ bytes.resize(len);
+ encode_variant(var, bytes.ptrw(), len, p_full_objects);
+}
+
+GD_PINVOKE_EXPORT void godotsharp_bytes2var(const godot_packed_array *p_bytes, bool p_allow_objects, godot_variant *r_ret) {
+ const PackedByteArray *bytes = reinterpret_cast<const PackedByteArray *>(p_bytes);
+ Variant ret;
+ Error err = decode_variant(ret, bytes->ptr(), bytes->size(), nullptr, p_allow_objects);
+ if (err != OK) {
+ ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
+ }
+ memnew_placement(r_ret, Variant(ret));
+}
+
+GD_PINVOKE_EXPORT int godotsharp_hash(const godot_variant *p_var) {
+ return reinterpret_cast<const Variant *>(p_var)->hash();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_convert(const godot_variant *p_what, int32_t p_type, godot_variant *r_ret) {
+ const Variant *args[1] = { reinterpret_cast<const Variant *>(p_what) };
+ Callable::CallError ce;
+ Variant ret;
+ Variant::construct(Variant::Type(p_type), ret, args, 1, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ memnew_placement(r_ret, Variant);
+ ERR_FAIL_MSG("Unable to convert parameter from '" +
+ Variant::get_type_name(reinterpret_cast<const Variant *>(p_what)->get_type()) +
+ "' to '" + Variant::get_type_name(Variant::Type(p_type)) + "'.");
+ }
+ memnew_placement(r_ret, Variant(ret));
+}
+
+GD_PINVOKE_EXPORT Object *godotsharp_instance_from_id(uint64_t p_instance_id) {
+ return ObjectDB::get_instance(ObjectID(p_instance_id));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_object_to_string(Object *p_ptr, godot_string *r_str) {
+#ifdef DEBUG_ENABLED
+ // Cannot happen in C#; would get an ObjectDisposedException instead.
+ CRASH_COND(p_ptr == nullptr);
+#endif
+ // Can't call 'Object::to_string()' here, as that can end up calling 'ToString' again resulting in an endless circular loop.
+ memnew_placement(r_str,
+ String("[" + p_ptr->get_class() + ":" + itos(p_ptr->get_instance_id()) + "]"));
+}
+
#ifdef __cplusplus
}
#endif
// We need this to prevent the functions from being stripped.
-void *godotsharp_pinvoke_funcs[138] = {
+void *godotsharp_pinvoke_funcs[164] = {
(void *)godotsharp_method_bind_get_method,
(void *)godotsharp_get_class_constructor,
(void *)godotsharp_invoke_class_constructor,
@@ -982,5 +1166,31 @@ void *godotsharp_pinvoke_funcs[138] = {
(void *)godotsharp_node_path_get_name_count,
(void *)godotsharp_node_path_get_subname,
(void *)godotsharp_node_path_get_subname_count,
- (void *)godotsharp_node_path_is_absolute
+ (void *)godotsharp_node_path_is_absolute,
+ (void *)godotsharp_randomize,
+ (void *)godotsharp_randi,
+ (void *)godotsharp_randf,
+ (void *)godotsharp_randi_range,
+ (void *)godotsharp_randf_range,
+ (void *)godotsharp_randfn,
+ (void *)godotsharp_seed,
+ (void *)godotsharp_rand_from_seed,
+ (void *)godotsharp_weakref,
+ (void *)godotsharp_str,
+ (void *)godotsharp_print,
+ (void *)godotsharp_print_rich,
+ (void *)godotsharp_printerr,
+ (void *)godotsharp_printt,
+ (void *)godotsharp_prints,
+ (void *)godotsharp_printraw,
+ (void *)godotsharp_pusherror,
+ (void *)godotsharp_pushwarning,
+ (void *)godotsharp_var2str,
+ (void *)godotsharp_str2var,
+ (void *)godotsharp_var2bytes,
+ (void *)godotsharp_bytes2var,
+ (void *)godotsharp_hash,
+ (void *)godotsharp_convert,
+ (void *)godotsharp_instance_from_id,
+ (void *)godotsharp_object_to_string,
};
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index b45b71aea7..bf387be4c8 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -442,14 +442,12 @@ bool GDMono::_are_api_assemblies_out_of_sync() {
return out_of_sync;
}
-void godot_register_gd_icalls();
void godot_register_object_icalls();
void godot_register_scene_tree_icalls();
void godot_register_placeholder_icalls();
void GDMono::_register_internal_calls() {
// Registers internal calls that were not generated.
- godot_register_gd_icalls();
godot_register_object_icalls();
godot_register_scene_tree_icalls();
godot_register_placeholder_icalls();
@@ -987,6 +985,8 @@ Error GDMono::_load_scripts_domain() {
Error GDMono::_unload_scripts_domain() {
ERR_FAIL_NULL_V(scripts_domain, ERR_BUG);
+ CSharpLanguage::get_singleton()->_on_scripts_domain_about_to_unload();
+
print_verbose("Mono: Finalizing scripts domain...");
if (mono_domain_get() != root_domain) {
@@ -1040,8 +1040,6 @@ Error GDMono::_unload_scripts_domain() {
Error GDMono::reload_scripts_domain() {
ERR_FAIL_COND_V(!runtime_initialized, ERR_BUG);
- CSharpLanguage::get_singleton()->_on_scripts_domain_about_to_unload();
-
if (scripts_domain) {
Error domain_unload_err = _unload_scripts_domain();
ERR_FAIL_COND_V_MSG(domain_unload_err != OK, domain_unload_err, "Mono: Failed to unload scripts domain.");
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index 08660e3701..54e49cf5f5 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -116,7 +116,6 @@ void CachedData::clear_godot_api_cache() {
methodthunk_GodotObject_Dispose.nullify();
methodthunk_SignalAwaiter_SignalCallback.nullify();
- methodthunk_GodotTaskScheduler_Activate.nullify();
methodthunk_Delegate_Equals.nullify();
@@ -137,8 +136,6 @@ void CachedData::clear_godot_api_cache() {
methodthunk_Marshaling_SetFieldValue.nullify();
methodthunk_MarshalUtils_TypeHasFlagsAttribute.nullify();
-
- task_scheduler_handle = Ref<MonoGCHandleRef>();
}
#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
@@ -197,7 +194,6 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(GodotObject, Dispose, CACHED_CLASS(GodotObject)->get_method("Dispose", 0));
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1));
- CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0));
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TrySerializeDelegateWithGCHandle, GODOT_API_CLASS(DelegateUtils)->get_method("TrySerializeDelegateWithGCHandle", 2));
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TryDeserializeDelegateWithGCHandle, GODOT_API_CLASS(DelegateUtils)->get_method("TryDeserializeDelegateWithGCHandle", 2));
@@ -233,10 +229,16 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4));
#endif
- // TODO Move to CSharpLanguage::init() and do handle disposal
- MonoObject *task_scheduler = mono_object_new(mono_domain_get(), GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
- GDMonoUtils::runtime_object_init(task_scheduler, GODOT_API_CLASS(GodotTaskScheduler));
- cached_data.task_scheduler_handle = MonoGCHandleRef::create_strong(task_scheduler);
+ MonoException *exc = nullptr;
+ GDMono::get_singleton()
+ ->get_core_api_assembly()
+ ->get_class("Godot", "Dispatcher")
+ ->get_method("InitializeDefaultGodotTaskScheduler")
+ ->invoke(nullptr, &exc);
+
+ if (exc) {
+ GDMonoUtils::debug_unhandled_exception(exc);
+ }
cached_data.godot_api_cache_updated = true;
}
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 0db32b5885..5876583260 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -90,7 +90,6 @@ struct CachedData {
GDMonoMethodThunk<MonoObject *> methodthunk_GodotObject_Dispose;
GDMonoMethodThunk<MonoObject *, MonoArray *> methodthunk_SignalAwaiter_SignalCallback;
- GDMonoMethodThunk<MonoObject *> methodthunk_GodotTaskScheduler_Activate;
GDMonoMethodThunkR<MonoBoolean, MonoObject *, MonoObject *> methodthunk_Delegate_Equals;
@@ -114,8 +113,6 @@ struct CachedData {
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeHasFlagsAttribute;
- Ref<MonoGCHandleRef> task_scheduler_handle;
-
bool corlib_cache_updated;
bool godot_api_cache_updated;
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index ef6a008a25..8828ec588b 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -40,9 +40,7 @@ namespace GDMonoMarshal {
// TODO: Those are just temporary until the code that needs them is moved to C#
Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_variant) {
- if (p_type.type_encoding == MONO_TYPE_VOID) {
- return Variant::NIL;
- }
+ CRASH_COND(p_type.type_class == nullptr);
MonoReflectionType *refltype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
MonoBoolean nil_is_variant = false;
@@ -137,59 +135,6 @@ Variant mono_object_to_variant_no_err(MonoObject *p_obj) {
return mono_object_to_variant_impl(p_obj, /* fail_with_err: */ false);
}
-String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) {
- if (p_obj == nullptr) {
- return String("null");
- }
-
- Variant var = GDMonoMarshal::mono_object_to_variant_no_err(p_obj);
-
- if (var.get_type() == Variant::NIL) { // `&& p_obj != nullptr` but omitted because always true
- // Cannot convert MonoObject* to Variant; fallback to 'ToString()'.
- MonoException *exc = nullptr;
- MonoString *mono_str = GDMonoUtils::object_to_string(p_obj, &exc);
-
- if (exc) {
- if (r_exc) {
- *r_exc = exc;
- }
- return String();
- }
-
- return GDMonoMarshal::mono_string_to_godot(mono_str);
- } else {
- return var.operator String();
- }
-}
-
-MonoArray *Array_to_mono_array(const Array &p_array) {
- int length = p_array.size();
- MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), length);
-
- for (int i = 0; i < length; i++) {
- MonoObject *boxed = variant_to_mono_object(p_array[i]);
- mono_array_setref(ret, i, boxed);
- }
-
- return ret;
-}
-
-Array mono_array_to_Array(MonoArray *p_array) {
- Array ret;
- if (!p_array) {
- return ret;
- }
- int length = mono_array_length(p_array);
- ret.resize(length);
-
- for (int i = 0; i < length; i++) {
- MonoObject *elem = mono_array_get(p_array, MonoObject *, i);
- ret[i] = mono_object_to_variant(elem);
- }
-
- return ret;
-}
-
MonoArray *PackedStringArray_to_mono_array(const PackedStringArray &p_array) {
const String *r = p_array.ptr();
int length = p_array.size();
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 16683de51a..fbe5795df5 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -88,15 +88,6 @@ _FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant *p_var) {
Variant mono_object_to_variant(MonoObject *p_obj);
Variant mono_object_to_variant_no_err(MonoObject *p_obj);
-/// Tries to convert the MonoObject* to Variant and then convert the Variant to String.
-/// If the MonoObject* cannot be converted to Variant, then 'ToString()' is called instead.
-String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc);
-
-// Array
-
-MonoArray *Array_to_mono_array(const Array &p_array);
-Array mono_array_to_Array(MonoArray *p_array);
-
// PackedStringArray
MonoArray *PackedStringArray_to_mono_array(const PackedStringArray &p_array);
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
index 04f6005338..97d3c82230 100644
--- a/modules/mono/mono_gd/gd_mono_method.cpp
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -253,9 +253,13 @@ const MethodInfo &GDMonoMethod::get_method_info() {
method_info.name = name;
bool nil_is_variant = false;
- method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type, &nil_is_variant), "");
- if (method_info.return_val.type == Variant::NIL && nil_is_variant) {
- method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ if (return_type.type_encoding == MONO_TYPE_VOID) {
+ method_info.return_val = PropertyInfo(Variant::NIL, "");
+ } else {
+ method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type, &nil_is_variant), "");
+ if (method_info.return_val.type == Variant::NIL && nil_is_variant) {
+ method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
}
Vector<StringName> names;