summaryrefslogtreecommitdiff
path: root/modules/mono/glue
diff options
context:
space:
mode:
authorIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2021-05-03 15:21:06 +0200
committerIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2022-08-22 03:35:59 +0200
commit124fbf95f8ef065215e9fcc937a370dbef3196e1 (patch)
treef2b05a195cd8a9d5a4bc8e527930873349d99a4b /modules/mono/glue
parent0c5f254956f0115e363ce08045dd178dc30b54f8 (diff)
C#: Move marshaling logic and generated glue to C#
We will be progressively moving most code to C#. The plan is to only use Mono's embedding APIs to set things at launch. This will make it much easier to later support CoreCLR too which doesn't have rich embedding APIs. Additionally the code in C# is more maintainable and makes it easier to implement new features, e.g.: runtime codegen which we could use to avoid using reflection for marshaling everytime a field, property or method is accessed. SOME NOTES ON INTEROP We make the same assumptions as GDNative about the size of the Godot structures we use. We take it a bit further by also assuming the layout of fields in some cases, which is riskier but let's us squeeze out some performance by avoiding unnecessary managed to native calls. Code that deals with native structs is less safe than before as there's no RAII and copy constructors in C#. It's like using the GDNative C API directly. One has to take special care to free values they own. Perhaps we could use roslyn analyzers to check this, but I don't know any that uses attributes to determine what's owned or borrowed. As to why we maily use pointers for native structs instead of ref/out: - AFAIK (and confirmed with a benchmark) ref/out are pinned during P/Invoke calls and that has a cost. - Native struct fields can't be ref/out in the first place. - A `using` local can't be passed as ref/out, only `in`. Calling a method or property on an `in` value makes a silent copy, so we want to avoid `in`. REGARDING THE BUILD SYSTEM There's no longer a `mono_glue=yes/no` SCons options. We no longer need to build with `mono_glue=no`, generate the glue and then build again with `mono_glue=yes`. We build only once and generate the glue (which is in C# now). However, SCons no longer builds the C# projects for us. Instead one must run `build_assemblies.py`, e.g.: ```sh %godot_src_root%/modules/mono/build_scripts/build_assemblies.py \ --godot-output-dir=%godot_src_root%/bin \ --godot-target=release_debug` ``` We could turn this into a custom build target, but I don't know how to do that with SCons (it's possible with Meson). OTHER NOTES Most of the moved code doesn't follow the C# naming convention and still has the word Mono in the names despite no longer dealing with Mono's embedding APIs. This is just temporary while transitioning, to make it easier to understand what was moved where.
Diffstat (limited to 'modules/mono/glue')
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs279
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs59
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs314
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs23
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs141
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs438
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs32
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs1370
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs346
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs70
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs33
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs335
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs119
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs92
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Object.exceptions.cs135
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs85
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs23
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs67
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj.DotSettings5
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj.DotSettings4
-rw-r--r--modules/mono/glue/base_object_glue.cpp18
-rw-r--r--modules/mono/glue/collections_glue.cpp154
-rw-r--r--modules/mono/glue/gd_glue.cpp22
-rw-r--r--modules/mono/glue/glue_header.h91
-rw-r--r--modules/mono/glue/node_path_glue.cpp (renamed from modules/mono/glue/nodepath_glue.cpp)33
-rw-r--r--modules/mono/glue/placeholder_glue.cpp (renamed from modules/mono/glue/rid_glue.cpp)44
-rw-r--r--modules/mono/glue/runtime_interop.cpp786
-rw-r--r--modules/mono/glue/scene_tree_glue.cpp15
-rw-r--r--modules/mono/glue/string_glue.cpp4
-rw-r--r--modules/mono/glue/string_name_glue.cpp62
35 files changed, 4180 insertions, 1058 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
new file mode 100644
index 0000000000..3103fa78c7
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
@@ -0,0 +1,7 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+ <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
+ <s:Boolean x:Key="/Default/UserDictionary/Words/=gdnative/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/UserDictionary/Words/=godotsharp/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/UserDictionary/Words/=icall/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/UserDictionary/Words/=quat/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/UserDictionary/Words/=vcall/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index a412047196..c32895baab 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -1,47 +1,28 @@
using System;
using System.Collections.Generic;
using System.Collections;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
+using Godot.NativeInterop;
namespace Godot.Collections
{
- internal class ArraySafeHandle : SafeHandle
- {
- public ArraySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
- {
- this.handle = handle;
- }
-
- public override bool IsInvalid
- {
- get { return handle == IntPtr.Zero; }
- }
-
- protected override bool ReleaseHandle()
- {
- Array.godot_icall_Array_Dtor(handle);
- return true;
- }
- }
-
/// <summary>
/// Wrapper around Godot's Array class, an array of Variant
/// typed elements allocated in the engine in C++. Useful when
/// interfacing with the engine. Otherwise prefer .NET collections
/// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
/// </summary>
- public class Array : IList, IDisposable
+ public sealed class Array : IList, IDisposable
{
- private ArraySafeHandle _safeHandle;
- private bool _disposed = false;
+ internal godot_array NativeValue;
/// <summary>
/// Constructs a new empty <see cref="Array"/>.
/// </summary>
public Array()
{
- _safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
+ godot_icall_Array_Ctor(out NativeValue);
}
/// <summary>
@@ -58,6 +39,7 @@ namespace Godot.Collections
Add(element);
}
+ // TODO: This must be removed. Lots of silent mistakes as it takes pretty much anything.
/// <summary>
/// Constructs a new <see cref="Array"/> from the given objects.
/// </summary>
@@ -69,25 +51,37 @@ namespace Godot.Collections
{
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
}
- _safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor_MonoArray(array));
+
+ godot_icall_Array_Ctor_MonoArray(array, out NativeValue);
}
- internal Array(ArraySafeHandle handle)
+ private Array(godot_array nativeValueToOwn)
{
- _safeHandle = handle;
+ NativeValue = nativeValueToOwn;
}
- internal Array(IntPtr handle)
+ // Explicit name to make it very clear
+ internal static Array CreateTakingOwnershipOfDisposableValue(godot_array nativeValueToOwn)
+ => new Array(nativeValueToOwn);
+
+ ~Array()
{
- _safeHandle = new ArraySafeHandle(handle);
+ Dispose(false);
}
- internal IntPtr GetPtr()
+ /// <summary>
+ /// Disposes of this <see cref="Array"/>.
+ /// </summary>
+ public void Dispose()
{
- if (_disposed)
- throw new ObjectDisposedException(GetType().FullName);
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
- return _safeHandle.DangerousGetHandle();
+ public void Dispose(bool disposing)
+ {
+ // Always dispose `NativeValue` even if disposing is true
+ NativeValue.Dispose();
}
/// <summary>
@@ -97,7 +91,9 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array Duplicate(bool deep = false)
{
- return new Array(godot_icall_Array_Duplicate(GetPtr(), deep));
+ godot_array newArray;
+ godot_icall_Array_Duplicate(ref NativeValue, deep, out newArray);
+ return CreateTakingOwnershipOfDisposableValue(newArray);
}
/// <summary>
@@ -107,7 +103,7 @@ namespace Godot.Collections
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
public Error Resize(int newSize)
{
- return godot_icall_Array_Resize(GetPtr(), newSize);
+ return godot_icall_Array_Resize(ref NativeValue, newSize);
}
/// <summary>
@@ -115,7 +111,7 @@ namespace Godot.Collections
/// </summary>
public void Shuffle()
{
- godot_icall_Array_Shuffle(GetPtr());
+ godot_icall_Array_Shuffle(ref NativeValue);
}
/// <summary>
@@ -126,26 +122,9 @@ namespace Godot.Collections
/// <returns>A new Godot Array with the contents of both arrays.</returns>
public static Array operator +(Array left, Array right)
{
- return new Array(godot_icall_Array_Concatenate(left.GetPtr(), right.GetPtr()));
- }
-
- // IDisposable
-
- /// <summary>
- /// Disposes of this <see cref="Array"/>.
- /// </summary>
- public void Dispose()
- {
- if (_disposed)
- return;
-
- if (_safeHandle != null)
- {
- _safeHandle.Dispose();
- _safeHandle = null;
- }
-
- _disposed = true;
+ godot_array newArray;
+ godot_icall_Array_Concatenate(ref left.NativeValue, ref right.NativeValue, out newArray);
+ return CreateTakingOwnershipOfDisposableValue(newArray);
}
// IList
@@ -160,8 +139,16 @@ namespace Godot.Collections
/// <value>The object at the given <paramref name="index"/>.</value>
public object this[int index]
{
- get => godot_icall_Array_At(GetPtr(), index);
- set => godot_icall_Array_SetAt(GetPtr(), index, value);
+ get
+ {
+ godot_icall_Array_At(ref NativeValue, index, out godot_variant elem);
+ unsafe
+ {
+ using (elem)
+ return Marshaling.variant_to_mono_object(&elem);
+ }
+ }
+ set => godot_icall_Array_SetAt(ref NativeValue, index, value);
}
/// <summary>
@@ -170,19 +157,19 @@ namespace Godot.Collections
/// </summary>
/// <param name="value">The object to add.</param>
/// <returns>The new size after adding the object.</returns>
- public int Add(object value) => godot_icall_Array_Add(GetPtr(), value);
+ public int Add(object value) => godot_icall_Array_Add(ref NativeValue, value);
/// <summary>
/// Checks if this <see cref="Array"/> contains the given object.
/// </summary>
/// <param name="value">The item to look for.</param>
/// <returns>Whether or not this array contains the given object.</returns>
- public bool Contains(object value) => godot_icall_Array_Contains(GetPtr(), value);
+ public bool Contains(object value) => godot_icall_Array_Contains(ref NativeValue, value);
/// <summary>
/// Erases all items from this <see cref="Array"/>.
/// </summary>
- public void Clear() => godot_icall_Array_Clear(GetPtr());
+ public void Clear() => godot_icall_Array_Clear(ref NativeValue);
/// <summary>
/// Searches this <see cref="Array"/> for an object
@@ -190,7 +177,7 @@ namespace Godot.Collections
/// </summary>
/// <param name="value">The object to search for.</param>
/// <returns>The index of the object, or -1 if not found.</returns>
- public int IndexOf(object value) => godot_icall_Array_IndexOf(GetPtr(), value);
+ public int IndexOf(object value) => godot_icall_Array_IndexOf(ref NativeValue, value);
/// <summary>
/// Inserts a new object at a given position in the array.
@@ -200,20 +187,20 @@ namespace Godot.Collections
/// </summary>
/// <param name="index">The index to insert at.</param>
/// <param name="value">The object to insert.</param>
- public void Insert(int index, object value) => godot_icall_Array_Insert(GetPtr(), index, value);
+ public void Insert(int index, object value) => godot_icall_Array_Insert(ref NativeValue, index, value);
/// <summary>
/// Removes the first occurrence of the specified <paramref name="value"/>
/// from this <see cref="Array"/>.
/// </summary>
/// <param name="value">The value to remove.</param>
- public void Remove(object value) => godot_icall_Array_Remove(GetPtr(), value);
+ public void Remove(object value) => godot_icall_Array_Remove(ref NativeValue, value);
/// <summary>
/// Removes an element from this <see cref="Array"/> by index.
/// </summary>
/// <param name="index">The index of the element to remove.</param>
- public void RemoveAt(int index) => godot_icall_Array_RemoveAt(GetPtr(), index);
+ public void RemoveAt(int index) => godot_icall_Array_RemoveAt(ref NativeValue, index);
// ICollection
@@ -222,7 +209,7 @@ namespace Godot.Collections
/// This is also known as the size or length of the array.
/// </summary>
/// <returns>The number of elements.</returns>
- public int Count => godot_icall_Array_Count(GetPtr());
+ public int Count => godot_icall_Array_Count(ref NativeValue);
object ICollection.SyncRoot => this;
@@ -243,7 +230,7 @@ namespace Godot.Collections
throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
// Internal call may throw ArgumentException
- godot_icall_Array_CopyTo(GetPtr(), array, index);
+ godot_icall_Array_CopyTo(ref NativeValue, array, index);
}
// IEnumerable
@@ -268,73 +255,71 @@ namespace Godot.Collections
/// <returns>A string representation of this array.</returns>
public override string ToString()
{
- return godot_icall_Array_ToString(GetPtr());
+ return godot_icall_Array_ToString(ref NativeValue);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Array_Ctor();
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Array_Ctor_MonoArray(System.Array array);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Array_Dtor(IntPtr ptr);
+ internal static extern void godot_icall_Array_Ctor(out godot_array dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object godot_icall_Array_At(IntPtr ptr, int index);
+ internal static extern void godot_icall_Array_Ctor_MonoArray(System.Array array, out godot_array dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object godot_icall_Array_At_Generic(IntPtr ptr, int index, int elemTypeEncoding, IntPtr elemTypeClass);
+ internal static extern void godot_icall_Array_At(ref godot_array ptr, int index, out godot_variant elem);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
+ internal static extern void godot_icall_Array_SetAt(ref godot_array ptr, int index, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_Array_Count(IntPtr ptr);
+ internal static extern int godot_icall_Array_Count(ref godot_array ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_Array_Add(IntPtr ptr, object item);
+ internal static extern int godot_icall_Array_Add(ref godot_array ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Array_Clear(IntPtr ptr);
+ internal static extern void godot_icall_Array_Clear(ref godot_array ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Array_Concatenate(IntPtr left, IntPtr right);
+ internal static extern void godot_icall_Array_Concatenate(ref godot_array left, ref godot_array right, out godot_array dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Array_Contains(IntPtr ptr, object item);
+ internal static extern bool godot_icall_Array_Contains(ref godot_array ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
+ internal static extern void godot_icall_Array_CopyTo(ref godot_array ptr, System.Array array, int arrayIndex);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep);
+ internal static extern void godot_icall_Array_Duplicate(ref godot_array ptr, bool deep, out godot_array dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_Array_IndexOf(IntPtr ptr, object item);
+ internal static extern int godot_icall_Array_IndexOf(ref godot_array ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Array_Insert(IntPtr ptr, int index, object item);
+ internal static extern void godot_icall_Array_Insert(ref godot_array ptr, int index, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Array_Remove(IntPtr ptr, object item);
+ internal static extern bool godot_icall_Array_Remove(ref godot_array ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
+ internal static extern void godot_icall_Array_RemoveAt(ref godot_array ptr, int index);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern Error godot_icall_Array_Resize(IntPtr ptr, int newSize);
+ internal static extern Error godot_icall_Array_Resize(ref godot_array ptr, int newSize);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern Error godot_icall_Array_Shuffle(IntPtr ptr);
+ internal static extern Error godot_icall_Array_Shuffle(ref godot_array ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
+ internal static extern string godot_icall_Array_ToString(ref godot_array ptr);
+ }
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern string godot_icall_Array_ToString(IntPtr ptr);
+ internal interface IGenericGodotArray
+ {
+ Array UnderlyingArray { get; }
+ Type TypeOfElements { get; }
}
+ // TODO: Now we should be able to avoid boxing
/// <summary>
/// Typed wrapper around Godot's Array class, an array of Variant
/// typed elements allocated in the engine in C++. Useful when
@@ -342,24 +327,29 @@ namespace Godot.Collections
/// such as arrays or <see cref="List{T}"/>.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
- public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
+ [SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
+ public sealed class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>, IGenericGodotArray
{
- private Array _objectArray;
+ private readonly Array _underlyingArray;
- internal static int elemTypeEncoding;
- internal static IntPtr elemTypeClass;
+ internal ref godot_array NativeValue => ref _underlyingArray.NativeValue;
- static Array()
- {
- Array.godot_icall_Array_Generic_GetElementTypeInfo(typeof(T), out elemTypeEncoding, out elemTypeClass);
- }
+ // ReSharper disable StaticMemberInGenericType
+ // Warning is about unique static fields being created for each generic type combination:
+ // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
+ // In our case this is exactly what we want.
+ private static readonly Type TypeOfElements = typeof(T);
+ // ReSharper restore StaticMemberInGenericType
+
+ Array IGenericGodotArray.UnderlyingArray => _underlyingArray;
+ Type IGenericGodotArray.TypeOfElements => TypeOfElements;
/// <summary>
/// Constructs a new empty <see cref="Array{T}"/>.
/// </summary>
public Array()
{
- _objectArray = new Array();
+ _underlyingArray = new Array();
}
/// <summary>
@@ -372,7 +362,7 @@ namespace Godot.Collections
if (collection == null)
throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
- _objectArray = new Array(collection);
+ _underlyingArray = new Array(collection);
}
/// <summary>
@@ -386,7 +376,8 @@ namespace Godot.Collections
{
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
}
- _objectArray = new Array(array);
+
+ _underlyingArray = new Array(array);
}
/// <summary>
@@ -395,23 +386,12 @@ namespace Godot.Collections
/// <param name="array">The untyped array to construct from.</param>
public Array(Array array)
{
- _objectArray = array;
- }
-
- internal Array(IntPtr handle)
- {
- _objectArray = new Array(handle);
- }
-
- internal Array(ArraySafeHandle handle)
- {
- _objectArray = new Array(handle);
+ _underlyingArray = array;
}
- internal IntPtr GetPtr()
- {
- return _objectArray.GetPtr();
- }
+ // Explicit name to make it very clear
+ internal static Array<T> CreateTakingOwnershipOfDisposableValue(godot_array nativeValueToOwn)
+ => new Array<T>(Array.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
/// <summary>
/// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>.
@@ -419,7 +399,7 @@ namespace Godot.Collections
/// <param name="from">The typed array to convert.</param>
public static explicit operator Array(Array<T> from)
{
- return from._objectArray;
+ return from._underlyingArray;
}
/// <summary>
@@ -429,7 +409,7 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array<T> Duplicate(bool deep = false)
{
- return new Array<T>(_objectArray.Duplicate(deep));
+ return new Array<T>(_underlyingArray.Duplicate(deep));
}
/// <summary>
@@ -439,7 +419,7 @@ namespace Godot.Collections
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
public Error Resize(int newSize)
{
- return _objectArray.Resize(newSize);
+ return _underlyingArray.Resize(newSize);
}
/// <summary>
@@ -447,7 +427,7 @@ namespace Godot.Collections
/// </summary>
public void Shuffle()
{
- _objectArray.Shuffle();
+ _underlyingArray.Shuffle();
}
/// <summary>
@@ -458,7 +438,7 @@ namespace Godot.Collections
/// <returns>A new Godot Array with the contents of both arrays.</returns>
public static Array<T> operator +(Array<T> left, Array<T> right)
{
- return new Array<T>(left._objectArray + right._objectArray);
+ return new Array<T>(left._underlyingArray + right._underlyingArray);
}
// IList<T>
@@ -469,8 +449,16 @@ namespace Godot.Collections
/// <value>The value at the given <paramref name="index"/>.</value>
public T this[int index]
{
- get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); }
- set { _objectArray[index] = value; }
+ get
+ {
+ Array.godot_icall_Array_At(ref _underlyingArray.NativeValue, index, out godot_variant elem);
+ unsafe
+ {
+ using (elem)
+ return (T)Marshaling.variant_to_mono_object_of_type(&elem, TypeOfElements);
+ }
+ }
+ set => _underlyingArray[index] = value;
}
/// <summary>
@@ -481,7 +469,7 @@ namespace Godot.Collections
/// <returns>The index of the item, or -1 if not found.</returns>
public int IndexOf(T item)
{
- return _objectArray.IndexOf(item);
+ return _underlyingArray.IndexOf(item);
}
/// <summary>
@@ -494,7 +482,7 @@ namespace Godot.Collections
/// <param name="item">The item to insert.</param>
public void Insert(int index, T item)
{
- _objectArray.Insert(index, item);
+ _underlyingArray.Insert(index, item);
}
/// <summary>
@@ -503,7 +491,7 @@ namespace Godot.Collections
/// <param name="index">The index of the element to remove.</param>
public void RemoveAt(int index)
{
- _objectArray.RemoveAt(index);
+ _underlyingArray.RemoveAt(index);
}
// ICollection<T>
@@ -513,10 +501,7 @@ namespace Godot.Collections
/// This is also known as the size or length of the array.
/// </summary>
/// <returns>The number of elements.</returns>
- public int Count
- {
- get { return _objectArray.Count; }
- }
+ public int Count => _underlyingArray.Count;
bool ICollection<T>.IsReadOnly => false;
@@ -528,7 +513,7 @@ namespace Godot.Collections
/// <returns>The new size after adding the item.</returns>
public void Add(T item)
{
- _objectArray.Add(item);
+ _underlyingArray.Add(item);
}
/// <summary>
@@ -536,7 +521,7 @@ namespace Godot.Collections
/// </summary>
public void Clear()
{
- _objectArray.Clear();
+ _underlyingArray.Clear();
}
/// <summary>
@@ -546,7 +531,7 @@ namespace Godot.Collections
/// <returns>Whether or not this array contains the given item.</returns>
public bool Contains(T item)
{
- return _objectArray.Contains(item);
+ return _underlyingArray.Contains(item);
}
/// <summary>
@@ -563,17 +548,14 @@ namespace Godot.Collections
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
- // TODO This may be quite slow because every element access is an internal call.
- // It could be moved entirely to an internal call if we find out how to do the cast there.
-
- int count = _objectArray.Count;
+ int count = _underlyingArray.Count;
if (array.Length < (arrayIndex + count))
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
for (int i = 0; i < count; i++)
{
- array[arrayIndex] = (T)this[i];
+ array[arrayIndex] = this[i];
arrayIndex++;
}
}
@@ -586,7 +568,7 @@ namespace Godot.Collections
/// <returns>A <see langword="bool"/> indicating success or failure.</returns>
public bool Remove(T item)
{
- return Array.godot_icall_Array_Remove(GetPtr(), item);
+ return Array.godot_icall_Array_Remove(ref _underlyingArray.NativeValue, item);
}
// IEnumerable<T>
@@ -597,23 +579,20 @@ namespace Godot.Collections
/// <returns>An enumerator.</returns>
public IEnumerator<T> GetEnumerator()
{
- int count = _objectArray.Count;
+ int count = _underlyingArray.Count;
for (int i = 0; i < count; i++)
{
- yield return (T)this[i];
+ yield return this[i];
}
}
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>
/// Converts this <see cref="Array{T}"/> to a string.
/// </summary>
/// <returns>A string representation of this array.</returns>
- public override string ToString() => _objectArray.ToString();
+ public override string ToString() => _underlyingArray.ToString();
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
index 1dca9e6ea7..187d910f9f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
@@ -4,11 +4,53 @@ using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Godot.NativeInterop;
namespace Godot
{
internal static class DelegateUtils
{
+ // TODO: Move somewhere else once we need to for things other than delegates
+ internal static void FreeGCHandle(IntPtr delegateGCHandle)
+ => GCHandle.FromIntPtr(delegateGCHandle).Free();
+
+ internal static bool DelegateEquals(IntPtr delegateGCHandleA, IntPtr delegateGCHandleB)
+ {
+ var @delegateA = (Delegate)GCHandle.FromIntPtr(delegateGCHandleA).Target;
+ var @delegateB = (Delegate)GCHandle.FromIntPtr(delegateGCHandleB).Target;
+ return @delegateA == @delegateB;
+ }
+
+ internal static unsafe void InvokeWithVariantArgs(IntPtr delegateGCHandle, godot_variant** args, uint argc, godot_variant* ret)
+ {
+ // TODO: Optimize
+ var @delegate = (Delegate)GCHandle.FromIntPtr(delegateGCHandle).Target;
+ var managedArgs = new object[argc];
+
+ var parameterInfos = @delegate.Method.GetParameters();
+
+ var paramsLength = parameterInfos.Length;
+
+ if (argc != paramsLength)
+ {
+ throw new InvalidOperationException(
+ $"The delegate expects {paramsLength} arguments, but received {argc}.");
+ }
+
+ for (uint i = 0; i < argc; i++)
+ {
+ managedArgs[i] = Marshaling.variant_to_mono_object_of_type(
+ args[i], parameterInfos[i].ParameterType);
+ }
+
+ object invokeRet = @delegate.DynamicInvoke(managedArgs);
+
+ *ret = Marshaling.mono_object_to_variant(invokeRet);
+ }
+
+ // TODO: Check if we should be using BindingFlags.DeclaredOnly (would give better reflection performance).
+
private enum TargetKind : uint
{
Static,
@@ -16,7 +58,10 @@ namespace Godot
CompilerGenerated
}
- internal static bool TrySerializeDelegate(Delegate @delegate, Collections.Array serializedData)
+ internal static bool TrySerializeDelegateWithGCHandle(IntPtr delegateGCHandle, Collections.Array serializedData)
+ => TrySerializeDelegate((Delegate)GCHandle.FromIntPtr(delegateGCHandle).Target, serializedData);
+
+ private static bool TrySerializeDelegate(Delegate @delegate, Collections.Array serializedData)
{
if (@delegate is MulticastDelegate multicastDelegate)
{
@@ -72,12 +117,14 @@ namespace Godot
return true;
}
}
+ // ReSharper disable once RedundantNameQualifier
case Godot.Object godotObject:
{
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
writer.Write((ulong)TargetKind.GodotObject);
+ // ReSharper disable once RedundantCast
writer.Write((ulong)godotObject.GetInstanceId());
SerializeType(writer, @delegate.GetType());
@@ -93,7 +140,7 @@ namespace Godot
{
Type targetType = target.GetType();
- if (targetType.GetCustomAttribute(typeof(CompilerGeneratedAttribute), true) != null)
+ if (targetType.IsDefined(typeof(CompilerGeneratedAttribute), true))
{
// Compiler generated. Probably a closure. Try to serialize it.
@@ -213,6 +260,13 @@ namespace Godot
}
}
+ private static bool TryDeserializeDelegateWithGCHandle(Collections.Array serializedData, out IntPtr delegateGCHandle)
+ {
+ bool res = TryDeserializeDelegate(serializedData, out Delegate @delegate);
+ delegateGCHandle = GCHandle.ToIntPtr(GCHandle.Alloc(@delegate));
+ return res;
+ }
+
private static bool TryDeserializeDelegate(Collections.Array serializedData, out Delegate @delegate)
{
if (serializedData.Count == 1)
@@ -276,6 +330,7 @@ namespace Godot
case TargetKind.GodotObject:
{
ulong objectId = reader.ReadUInt64();
+ // ReSharper disable once RedundantNameQualifier
Godot.Object godotObject = GD.InstanceFromId(objectId);
if (godotObject == null)
return false;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index e80b6af68f..d0c7e4523b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -2,46 +2,28 @@ using System;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
+using Godot.NativeInterop;
using System.Diagnostics.CodeAnalysis;
namespace Godot.Collections
{
- internal class DictionarySafeHandle : SafeHandle
- {
- public DictionarySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
- {
- this.handle = handle;
- }
-
- public override bool IsInvalid
- {
- get { return handle == IntPtr.Zero; }
- }
-
- protected override bool ReleaseHandle()
- {
- Dictionary.godot_icall_Dictionary_Dtor(handle);
- return true;
- }
- }
-
/// <summary>
/// Wrapper around Godot's Dictionary class, a dictionary of Variant
/// typed elements allocated in the engine in C++. Useful when
/// interfacing with the engine.
/// </summary>
- public class Dictionary : IDictionary, IDisposable
+ public sealed class Dictionary :
+ IDictionary,
+ IDisposable
{
- private DictionarySafeHandle _safeHandle;
- private bool _disposed = false;
+ internal godot_dictionary NativeValue;
/// <summary>
/// Constructs a new empty <see cref="Dictionary"/>.
/// </summary>
public Dictionary()
{
- _safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
+ godot_icall_Dictionary_Ctor(out NativeValue);
}
/// <summary>
@@ -58,22 +40,18 @@ namespace Godot.Collections
Add(entry.Key, entry.Value);
}
- internal Dictionary(DictionarySafeHandle handle)
+ private Dictionary(godot_dictionary nativeValueToOwn)
{
- _safeHandle = handle;
+ NativeValue = nativeValueToOwn;
}
- internal Dictionary(IntPtr handle)
- {
- _safeHandle = new DictionarySafeHandle(handle);
- }
+ // Explicit name to make it very clear
+ internal static Dictionary CreateTakingOwnershipOfDisposableValue(godot_dictionary nativeValueToOwn)
+ => new Dictionary(nativeValueToOwn);
- internal IntPtr GetPtr()
+ ~Dictionary()
{
- if (_disposed)
- throw new ObjectDisposedException(GetType().FullName);
-
- return _safeHandle.DangerousGetHandle();
+ Dispose(false);
}
/// <summary>
@@ -81,16 +59,14 @@ namespace Godot.Collections
/// </summary>
public void Dispose()
{
- if (_disposed)
- return;
-
- if (_safeHandle != null)
- {
- _safeHandle.Dispose();
- _safeHandle = null;
- }
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
- _disposed = true;
+ public void Dispose(bool disposing)
+ {
+ // Always dispose `NativeValue` even if disposing is true
+ NativeValue.Dispose();
}
/// <summary>
@@ -100,7 +76,9 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary Duplicate(bool deep = false)
{
- return new Dictionary(godot_icall_Dictionary_Duplicate(GetPtr(), deep));
+ godot_dictionary newDictionary;
+ godot_icall_Dictionary_Duplicate(ref NativeValue, deep, out newDictionary);
+ return CreateTakingOwnershipOfDisposableValue(newDictionary);
}
// IDictionary
@@ -112,8 +90,9 @@ namespace Godot.Collections
{
get
{
- IntPtr handle = godot_icall_Dictionary_Keys(GetPtr());
- return new Array(new ArraySafeHandle(handle));
+ godot_array keysArray;
+ godot_icall_Dictionary_Keys(ref NativeValue, out keysArray);
+ return Array.CreateTakingOwnershipOfDisposableValue(keysArray);
}
}
@@ -124,16 +103,19 @@ namespace Godot.Collections
{
get
{
- IntPtr handle = godot_icall_Dictionary_Values(GetPtr());
- return new Array(new ArraySafeHandle(handle));
+ godot_array valuesArray;
+ godot_icall_Dictionary_Values(ref NativeValue, out valuesArray);
+ return Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
}
}
private (Array keys, Array values, int count) GetKeyValuePairs()
{
- int count = godot_icall_Dictionary_KeyValuePairs(GetPtr(), out IntPtr keysHandle, out IntPtr valuesHandle);
- Array keys = new Array(new ArraySafeHandle(keysHandle));
- Array values = new Array(new ArraySafeHandle(valuesHandle));
+ godot_array keysArray;
+ godot_array valuesArray;
+ int count = godot_icall_Dictionary_KeyValuePairs(ref NativeValue, out keysArray, out valuesArray);
+ var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
+ var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
return (keys, values, count);
}
@@ -147,8 +129,16 @@ namespace Godot.Collections
/// <value>The object at the given <paramref name="key"/>.</value>
public object this[object key]
{
- get => godot_icall_Dictionary_GetValue(GetPtr(), key);
- set => godot_icall_Dictionary_SetValue(GetPtr(), key, value);
+ get
+ {
+ godot_icall_Dictionary_GetValue(ref NativeValue, key, out godot_variant value);
+ unsafe
+ {
+ using (value)
+ return Marshaling.variant_to_mono_object(&value);
+ }
+ }
+ set => godot_icall_Dictionary_SetValue(ref NativeValue, key, value);
}
/// <summary>
@@ -157,19 +147,19 @@ namespace Godot.Collections
/// </summary>
/// <param name="key">The key at which to add the object.</param>
/// <param name="value">The object to add.</param>
- public void Add(object key, object value) => godot_icall_Dictionary_Add(GetPtr(), key, value);
+ public void Add(object key, object value) => godot_icall_Dictionary_Add(ref NativeValue, key, value);
/// <summary>
/// Erases all items from this <see cref="Dictionary"/>.
/// </summary>
- public void Clear() => godot_icall_Dictionary_Clear(GetPtr());
+ public void Clear() => godot_icall_Dictionary_Clear(ref NativeValue);
/// <summary>
/// Checks if this <see cref="Dictionary"/> contains the given key.
/// </summary>
/// <param name="key">The key to look for.</param>
/// <returns>Whether or not this dictionary contains the given key.</returns>
- public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(GetPtr(), key);
+ public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(ref NativeValue, key);
/// <summary>
/// Gets an enumerator for this <see cref="Dictionary"/>.
@@ -181,7 +171,7 @@ namespace Godot.Collections
/// Removes an element from this <see cref="Dictionary"/> by key.
/// </summary>
/// <param name="key">The key of the element to remove.</param>
- public void Remove(object key) => godot_icall_Dictionary_RemoveKey(GetPtr(), key);
+ public void Remove(object key) => godot_icall_Dictionary_RemoveKey(ref NativeValue, key);
// ICollection
@@ -194,7 +184,7 @@ namespace Godot.Collections
/// This is also known as the size or length of the dictionary.
/// </summary>
/// <returns>The number of elements.</returns>
- public int Count => godot_icall_Dictionary_Count(GetPtr());
+ public int Count => godot_icall_Dictionary_Count(ref NativeValue);
/// <summary>
/// Copies the elements of this <see cref="Dictionary"/> to the given
@@ -258,8 +248,17 @@ namespace Godot.Collections
private void UpdateEntry()
{
_dirty = false;
- godot_icall_Dictionary_KeyValuePairAt(_dictionary.GetPtr(), _index, out object key, out object value);
- _entry = new DictionaryEntry(key, value);
+ godot_icall_Dictionary_KeyValuePairAt(ref _dictionary.NativeValue, _index, out var vKey, out var vValue);
+ unsafe
+ {
+ using (vKey)
+ using (vValue)
+ {
+ var key = Marshaling.variant_to_mono_object(&vKey);
+ var value = Marshaling.variant_to_mono_object(&vValue);
+ _entry = new DictionaryEntry(key, value);
+ }
+ }
}
public object Key => Entry.Key;
@@ -286,76 +285,70 @@ namespace Godot.Collections
/// <returns>A string representation of this dictionary.</returns>
public override string ToString()
{
- return godot_icall_Dictionary_ToString(GetPtr());
+ return godot_icall_Dictionary_ToString(ref NativeValue);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Dictionary_Ctor();
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Dictionary_Dtor(IntPtr ptr);
+ internal static extern void godot_icall_Dictionary_Ctor(out godot_dictionary dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
+ internal static extern void godot_icall_Dictionary_GetValue(ref godot_dictionary ptr, object key, out godot_variant value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object godot_icall_Dictionary_GetValue_Generic(IntPtr ptr, object key, int valTypeEncoding, IntPtr valTypeClass);
+ internal static extern void godot_icall_Dictionary_SetValue(ref godot_dictionary ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
+ internal static extern void godot_icall_Dictionary_Keys(ref godot_dictionary ptr, out godot_array dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Dictionary_Keys(IntPtr ptr);
+ internal static extern void godot_icall_Dictionary_Values(ref godot_dictionary ptr, out godot_array dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Dictionary_Values(IntPtr ptr);
+ internal static extern int godot_icall_Dictionary_KeyValuePairs(ref godot_dictionary ptr, out godot_array keys, out godot_array values);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_Dictionary_Count(IntPtr ptr);
+ internal static extern void godot_icall_Dictionary_KeyValuePairAt(ref godot_dictionary ptr, int index, out godot_variant key, out godot_variant value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values);
+ internal static extern void godot_icall_Dictionary_Add(ref godot_dictionary ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value);
+ internal static extern int godot_icall_Dictionary_Count(ref godot_dictionary ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Dictionary_KeyValuePairAt_Generic(IntPtr ptr, int index, out object key, out object value, int valueTypeEncoding, IntPtr valueTypeClass);
+ internal static extern void godot_icall_Dictionary_Clear(ref godot_dictionary ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value);
+ internal static extern bool godot_icall_Dictionary_Contains(ref godot_dictionary ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Dictionary_Clear(IntPtr ptr);
+ internal static extern bool godot_icall_Dictionary_ContainsKey(ref godot_dictionary ptr, object key);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value);
+ internal static extern void godot_icall_Dictionary_Duplicate(ref godot_dictionary ptr, bool deep, out godot_dictionary dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
+ internal static extern bool godot_icall_Dictionary_RemoveKey(ref godot_dictionary ptr, object key);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep);
+ internal static extern bool godot_icall_Dictionary_Remove(ref godot_dictionary ptr, object key, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
+ internal static extern bool godot_icall_Dictionary_TryGetValue(ref godot_dictionary ptr, object key, out godot_variant value);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_Dictionary_TryGetValue_Generic(IntPtr ptr, object key, out object value, int valTypeEncoding, IntPtr valTypeClass);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
+ internal static extern string godot_icall_Dictionary_ToString(ref godot_dictionary ptr);
+ }
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern string godot_icall_Dictionary_ToString(IntPtr ptr);
+ internal interface IGenericGodotDictionary
+ {
+ Dictionary UnderlyingDictionary { get; }
+ Type TypeOfKeys { get; }
+ Type TypeOfValues { get; }
}
+ // TODO: Now we should be able to avoid boxing
+
/// <summary>
/// Typed wrapper around Godot's Dictionary class, a dictionary of Variant
/// typed elements allocated in the engine in C++. Useful when
@@ -364,24 +357,32 @@ namespace Godot.Collections
/// </summary>
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
- public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>
+ public sealed class Dictionary<TKey, TValue> :
+ IDictionary<TKey, TValue>, IGenericGodotDictionary
{
- private readonly Dictionary _objectDict;
+ private readonly Dictionary _underlyingDict;
- internal static int valTypeEncoding;
- internal static IntPtr valTypeClass;
+ internal ref godot_dictionary NativeValue => ref _underlyingDict.NativeValue;
- static Dictionary()
- {
- Dictionary.godot_icall_Dictionary_Generic_GetValueTypeInfo(typeof(TValue), out valTypeEncoding, out valTypeClass);
- }
+ // ReSharper disable StaticMemberInGenericType
+ // Warning is about unique static fields being created for each generic type combination:
+ // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
+ // In our case this is exactly what we want.
+ private static readonly Type TypeOfKeys = typeof(TKey);
+
+ private static readonly Type TypeOfValues = typeof(TValue);
+ // ReSharper restore StaticMemberInGenericType
+
+ Dictionary IGenericGodotDictionary.UnderlyingDictionary => _underlyingDict;
+ Type IGenericGodotDictionary.TypeOfKeys => TypeOfKeys;
+ Type IGenericGodotDictionary.TypeOfValues => TypeOfValues;
/// <summary>
/// Constructs a new empty <see cref="Dictionary{TKey, TValue}"/>.
/// </summary>
public Dictionary()
{
- _objectDict = new Dictionary();
+ _underlyingDict = new Dictionary();
}
/// <summary>
@@ -391,19 +392,13 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(IDictionary<TKey, TValue> dictionary)
{
- _objectDict = new Dictionary();
+ _underlyingDict = new Dictionary();
if (dictionary == null)
throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
- // TODO: Can be optimized
-
- IntPtr godotDictionaryPtr = GetPtr();
-
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
- {
- Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value);
- }
+ Add(entry.Key, entry.Value);
}
/// <summary>
@@ -413,18 +408,12 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(Dictionary dictionary)
{
- _objectDict = dictionary;
+ _underlyingDict = dictionary;
}
- internal Dictionary(IntPtr handle)
- {
- _objectDict = new Dictionary(handle);
- }
-
- internal Dictionary(DictionarySafeHandle handle)
- {
- _objectDict = new Dictionary(handle);
- }
+ // Explicit name to make it very clear
+ internal static Dictionary<TKey, TValue> CreateTakingOwnershipOfDisposableValue(godot_dictionary nativeValueToOwn)
+ => new Dictionary<TKey, TValue>(Dictionary.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
/// <summary>
/// Converts this typed <see cref="Dictionary{TKey, TValue}"/> to an untyped <see cref="Dictionary"/>.
@@ -432,12 +421,7 @@ namespace Godot.Collections
/// <param name="from">The typed dictionary to convert.</param>
public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
{
- return from._objectDict;
- }
-
- internal IntPtr GetPtr()
- {
- return _objectDict.GetPtr();
+ return from._underlyingDict;
}
/// <summary>
@@ -447,7 +431,7 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary<TKey, TValue> Duplicate(bool deep = false)
{
- return new Dictionary<TKey, TValue>(_objectDict.Duplicate(deep));
+ return new Dictionary<TKey, TValue>(_underlyingDict.Duplicate(deep));
}
// IDictionary<TKey, TValue>
@@ -458,8 +442,16 @@ namespace Godot.Collections
/// <value>The value at the given <paramref name="key"/>.</value>
public TValue this[TKey key]
{
- get { return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(_objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); }
- set { _objectDict[key] = value; }
+ get
+ {
+ Dictionary.godot_icall_Dictionary_GetValue(ref _underlyingDict.NativeValue, key, out godot_variant value);
+ unsafe
+ {
+ using (value)
+ return (TValue)Marshaling.variant_to_mono_object_of_type(&value, TypeOfValues);
+ }
+ }
+ set => _underlyingDict[key] = value;
}
/// <summary>
@@ -469,8 +461,9 @@ namespace Godot.Collections
{
get
{
- IntPtr handle = Dictionary.godot_icall_Dictionary_Keys(_objectDict.GetPtr());
- return new Array<TKey>(new ArraySafeHandle(handle));
+ godot_array keyArray;
+ Dictionary.godot_icall_Dictionary_Keys(ref _underlyingDict.NativeValue, out keyArray);
+ return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray);
}
}
@@ -481,15 +474,25 @@ namespace Godot.Collections
{
get
{
- IntPtr handle = Dictionary.godot_icall_Dictionary_Values(_objectDict.GetPtr());
- return new Array<TValue>(new ArraySafeHandle(handle));
+ godot_array valuesArray;
+ Dictionary.godot_icall_Dictionary_Values(ref _underlyingDict.NativeValue, out valuesArray);
+ return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray);
}
}
private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
{
- Dictionary.godot_icall_Dictionary_KeyValuePairAt_Generic(GetPtr(), index, out object key, out object value, valTypeEncoding, valTypeClass);
- return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
+ Dictionary.godot_icall_Dictionary_KeyValuePairAt(ref _underlyingDict.NativeValue, index, out var vKey, out var vValue);
+ unsafe
+ {
+ using (vKey)
+ using (vValue)
+ {
+ var key = Marshaling.variant_to_mono_object_of_type(&vKey, TypeOfKeys);
+ var value = Marshaling.variant_to_mono_object_of_type(&vValue, TypeOfValues);
+ return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
+ }
+ }
}
/// <summary>
@@ -500,7 +503,7 @@ namespace Godot.Collections
/// <param name="value">The object to add.</param>
public void Add(TKey key, TValue value)
{
- _objectDict.Add(key, value);
+ _underlyingDict.Add(key, value);
}
/// <summary>
@@ -510,7 +513,7 @@ namespace Godot.Collections
/// <returns>Whether or not this dictionary contains the given key.</returns>
public bool ContainsKey(TKey key)
{
- return _objectDict.Contains(key);
+ return _underlyingDict.Contains(key);
}
/// <summary>
@@ -519,7 +522,7 @@ namespace Godot.Collections
/// <param name="key">The key of the element to remove.</param>
public bool Remove(TKey key)
{
- return Dictionary.godot_icall_Dictionary_RemoveKey(GetPtr(), key);
+ return Dictionary.godot_icall_Dictionary_RemoveKey(ref _underlyingDict.NativeValue, key);
}
/// <summary>
@@ -530,8 +533,18 @@ namespace Godot.Collections
/// <returns>If an object was found for the given <paramref name="key"/>.</returns>
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
- bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out object retValue, valTypeEncoding, valTypeClass);
- value = found ? (TValue)retValue : default;
+ bool found = Dictionary.godot_icall_Dictionary_TryGetValue(ref _underlyingDict.NativeValue, key, out godot_variant retValue);
+
+ unsafe
+ {
+ using (retValue)
+ {
+ value = found ?
+ (TValue)Marshaling.variant_to_mono_object_of_type(&retValue, TypeOfValues) :
+ default;
+ }
+ }
+
return found;
}
@@ -542,16 +555,13 @@ namespace Godot.Collections
/// This is also known as the size or length of the dictionary.
/// </summary>
/// <returns>The number of elements.</returns>
- public int Count
- {
- get { return _objectDict.Count; }
- }
+ public int Count => _underlyingDict.Count;
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
- _objectDict.Add(item.Key, item.Value);
+ _underlyingDict.Add(item.Key, item.Value);
}
/// <summary>
@@ -559,12 +569,12 @@ namespace Godot.Collections
/// </summary>
public void Clear()
{
- _objectDict.Clear();
+ _underlyingDict.Clear();
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
- return _objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
+ return _underlyingDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
}
/// <summary>
@@ -595,8 +605,7 @@ namespace Godot.Collections
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
- return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
- ;
+ return Dictionary.godot_icall_Dictionary_Remove(ref _underlyingDict.NativeValue, item.Key, item.Value);
}
// IEnumerable<KeyValuePair<TKey, TValue>>
@@ -613,15 +622,12 @@ namespace Godot.Collections
}
}
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>
/// Converts this <see cref="Dictionary{TKey, TValue}"/> to a string.
/// </summary>
/// <returns>A string representation of this dictionary.</returns>
- public override string ToString() => _objectDict.ToString();
+ public override string ToString() => _underlyingDict.ToString();
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs
index df130a5c77..7922f38ac5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs
@@ -1,6 +1,7 @@
using System;
using System.Runtime.CompilerServices;
using Godot.Collections;
+using Godot.NativeInterop;
namespace Godot
{
@@ -12,10 +13,12 @@ namespace Godot
/// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
public Array<T> GetNodesInGroup<T>(StringName group) where T : class
{
- return new Array<T>(godot_icall_SceneTree_get_nodes_in_group_Generic(GetPtr(this), StringName.GetPtr(group), typeof(T)));
+ godot_array array;
+ godot_icall_SceneTree_get_nodes_in_group_Generic(GetPtr(this), ref group.NativeValue, typeof(T), out array);
+ return Array<T>.CreateTakingOwnershipOfDisposableValue(array);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, IntPtr group, Type elemType);
+ internal static extern void godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, ref godot_string_name group, Type elemType, out godot_array dest);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index 236d0666bc..e8ea8f379b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -6,6 +6,7 @@ using real_t = System.Single;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -26,9 +27,10 @@ namespace Godot
/// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param>
/// <param name="allowObjects">If objects should be decoded.</param>
/// <returns>The decoded <c>Variant</c>.</returns>
- public static object Bytes2Var(byte[] bytes, bool allowObjects = false)
+ public static unsafe object Bytes2Var(byte[] bytes, bool allowObjects = false)
{
- return godot_icall_GD_bytes2var(bytes, allowObjects);
+ using var varBytes = Marshaling.mono_array_to_PackedByteArray(bytes);
+ return godot_icall_GD_bytes2var(&varBytes, allowObjects);
}
/// <summary>
@@ -527,7 +529,7 @@ namespace Godot
/// <returns>If the class exists in <see cref="ClassDB"/>.</returns>
public static bool TypeExists(StringName type)
{
- return godot_icall_GD_type_exists(StringName.GetPtr(type));
+ return godot_icall_GD_type_exists(ref type.NativeValue);
}
/// <summary>
@@ -539,9 +541,14 @@ namespace Godot
/// <param name="var">Variant that will be encoded.</param>
/// <param name="fullObjects">If objects should be serialized.</param>
/// <returns>The <c>Variant</c> encoded as an array of bytes.</returns>
- public static byte[] Var2Bytes(object var, bool fullObjects = false)
+ public static unsafe byte[] Var2Bytes(object var, bool fullObjects = false)
{
- return godot_icall_GD_var2bytes(var, fullObjects);
+ godot_packed_byte_array varBytes;
+ godot_icall_GD_var2bytes(var, fullObjects, &varBytes);
+ using (varBytes)
+ {
+ return Marshaling.PackedByteArray_to_mono_array(&varBytes);
+ }
}
/// <summary>
@@ -576,7 +583,7 @@ namespace Godot
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object godot_icall_GD_bytes2var(byte[] bytes, bool allowObjects);
+ 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);
@@ -636,10 +643,10 @@ namespace Godot
internal static extern object godot_icall_GD_str2var(string str);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool godot_icall_GD_type_exists(IntPtr type);
+ internal static extern bool godot_icall_GD_type_exists(ref godot_string_name type);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern byte[] godot_icall_GD_var2bytes(object what, bool fullObjects);
+ 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);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
index 50ae2eb112..733a8ac114 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
@@ -6,149 +6,8 @@ namespace Godot
internal static class MarshalUtils
{
/// <summary>
- /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="Collections.Array{T}"/>; otherwise returns <see langword="false"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static bool TypeIsGenericArray(Type type) =>
- type.GetGenericTypeDefinition() == typeof(Collections.Array<>);
-
- /// <summary>
- /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="Collections.Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static bool TypeIsGenericDictionary(Type type) =>
- type.GetGenericTypeDefinition() == typeof(Collections.Dictionary<,>);
-
- /// <summary>
- /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="List{T}"/>; otherwise returns <see langword="false"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static bool TypeIsSystemGenericList(Type type) =>
- type.GetGenericTypeDefinition() == typeof(List<>);
-
- /// <summary>
- /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static bool TypeIsSystemGenericDictionary(Type type) =>
- type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
-
- /// <summary>
- /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="IEnumerable{T}"/>; otherwise returns <see langword="false"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static bool TypeIsGenericIEnumerable(Type type) => type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
-
- /// <summary>
- /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="ICollection{T}"/>; otherwise returns <see langword="false"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static bool TypeIsGenericICollection(Type type) => type.GetGenericTypeDefinition() == typeof(ICollection<>);
-
- /// <summary>
- /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="IDictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>);
-
- /// <summary>
/// Returns <see langword="true"/> if the <see cref="FlagsAttribute"/> is applied to the given type.
/// </summary>
private static bool TypeHasFlagsAttribute(Type type) => type.IsDefined(typeof(FlagsAttribute), false);
-
- /// <summary>
- /// Returns the generic type definition of <paramref name="type"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="type"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static void GetGenericTypeDefinition(Type type, out Type genericTypeDefinition)
- {
- genericTypeDefinition = type.GetGenericTypeDefinition();
- }
-
- /// <summary>
- /// Gets the element type for the given <paramref name="arrayType"/>.
- /// </summary>
- /// <param name="arrayType">Type for the generic array.</param>
- /// <param name="elementType">Element type for the generic array.</param>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="arrayType"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static void ArrayGetElementType(Type arrayType, out Type elementType)
- {
- elementType = arrayType.GetGenericArguments()[0];
- }
-
- /// <summary>
- /// Gets the key type and the value type for the given <paramref name="dictionaryType"/>.
- /// </summary>
- /// <param name="dictionaryType">The type for the generic dictionary.</param>
- /// <param name="keyType">Key type for the generic dictionary.</param>
- /// <param name="valueType">Value type for the generic dictionary.</param>
- /// <exception cref="InvalidOperationException">
- /// Thrown when the given <paramref name="dictionaryType"/> is not a generic type.
- /// That is, <see cref="Type.IsGenericType"/> returns <see langword="false"/>.
- /// </exception>
- private static void DictionaryGetKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
- {
- var genericArgs = dictionaryType.GetGenericArguments();
- keyType = genericArgs[0];
- valueType = genericArgs[1];
- }
-
- /// <summary>
- /// Constructs a new <see cref="Type"/> from <see cref="Collections.Array{T}"/>
- /// where the generic type for the elements is <paramref name="elemType"/>.
- /// </summary>
- /// <param name="elemType">Element type for the array.</param>
- /// <returns>The generic array type with the specified element type.</returns>
- private static Type MakeGenericArrayType(Type elemType)
- {
- return typeof(Collections.Array<>).MakeGenericType(elemType);
- }
-
- /// <summary>
- /// Constructs a new <see cref="Type"/> from <see cref="Collections.Dictionary{TKey, TValue}"/>
- /// where the generic type for the keys is <paramref name="keyType"/> and
- /// for the values is <paramref name="valueType"/>.
- /// </summary>
- /// <param name="keyType">Key type for the dictionary.</param>
- /// <param name="valueType">Key type for the dictionary.</param>
- /// <returns>The generic dictionary type with the specified key and value types.</returns>
- private static Type MakeGenericDictionaryType(Type keyType, Type valueType)
- {
- return typeof(Collections.Dictionary<,>).MakeGenericType(keyType, valueType);
- }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
new file mode 100644
index 0000000000..6ee8cbc0bc
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
@@ -0,0 +1,438 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+#if REAL_T_IS_DOUBLE
+using real_t = System.Double;
+#else
+using real_t = System.Single;
+
+#endif
+
+namespace Godot.NativeInterop
+{
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_bool
+ {
+ public byte _value;
+
+ public unsafe godot_bool(bool value) => _value = *(byte*)&value;
+
+ public static unsafe implicit operator bool(godot_bool godotBool) => *(bool*)&godotBool._value;
+ public static implicit operator godot_bool(bool @bool) => new godot_bool(@bool);
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_ref : IDisposable
+ {
+ internal IntPtr _reference;
+
+ public void Dispose()
+ {
+ if (_reference == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_ref_destroy(ref this);
+ _reference = IntPtr.Zero;
+ }
+ }
+
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ internal enum godot_variant_call_error_error
+ {
+ GODOT_CALL_ERROR_CALL_OK = 0,
+ GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD,
+ GODOT_CALL_ERROR_CALL_ERROR_INVALID_ARGUMENT,
+ GODOT_CALL_ERROR_CALL_ERROR_TOO_MANY_ARGUMENTS,
+ GODOT_CALL_ERROR_CALL_ERROR_TOO_FEW_ARGUMENTS,
+ GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_variant_call_error
+ {
+ godot_variant_call_error_error error;
+ int argument;
+ int expected;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_variant : IDisposable
+ {
+ // Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
+ [FieldOffset(0)] private int _typeField;
+
+ // There's padding here
+
+ [FieldOffset(8)] internal godot_variant_data _data;
+
+ public Variant.Type _type
+ {
+ get => (Variant.Type)_typeField;
+ set => _typeField = (int)value;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ // ReSharper disable once InconsistentNaming
+ internal unsafe struct godot_variant_data
+ {
+ [FieldOffset(0)] public godot_bool _bool;
+ [FieldOffset(0)] public long _int;
+ [FieldOffset(0)] public double _float;
+ [FieldOffset(0)] public Transform2D* _transform2d;
+ [FieldOffset(0)] public AABB* _aabb;
+ [FieldOffset(0)] public Basis* _basis;
+ [FieldOffset(0)] public Transform3D* _transform3d;
+ [FieldOffset(0)] public Vector4* _vector4;
+ [FieldOffset(0)] public Vector4i* _vector4i;
+ [FieldOffset(0)] public Projection* _projection;
+ [FieldOffset(0)] private godot_variant_data_mem _mem;
+
+ // The following fields are not in the C++ union, but this is how they're stored in _mem.
+ [FieldOffset(0)] public godot_string_name _m_string_name;
+ [FieldOffset(0)] public godot_string _m_string;
+ [FieldOffset(0)] public Vector3 _m_vector3;
+ [FieldOffset(0)] public Vector3i _m_vector3i;
+ [FieldOffset(0)] public Vector2 _m_vector2;
+ [FieldOffset(0)] public Vector2i _m_vector2i;
+ [FieldOffset(0)] public Rect2 _m_rect2;
+ [FieldOffset(0)] public Rect2i _m_rect2i;
+ [FieldOffset(0)] public Plane _m_plane;
+ [FieldOffset(0)] public Quaternion _m_quaternion;
+ [FieldOffset(0)] public Color _m_color;
+ [FieldOffset(0)] public godot_node_path _m_node_path;
+ [FieldOffset(0)] public RID _m_rid;
+ [FieldOffset(0)] public godot_variant_obj_data _m_obj_data;
+ [FieldOffset(0)] public godot_callable _m_callable;
+ [FieldOffset(0)] public godot_signal _m_signal;
+ [FieldOffset(0)] public godot_dictionary _m_dictionary;
+ [FieldOffset(0)] public godot_array _m_array;
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_variant_obj_data
+ {
+ public UInt64 id;
+ public IntPtr obj;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ private struct godot_variant_data_mem
+ {
+#pragma warning disable 169
+ private real_t _mem0;
+ private real_t _mem1;
+ private real_t _mem2;
+ private real_t _mem3;
+#pragma warning restore 169
+ }
+ }
+
+ public void Dispose()
+ {
+ switch (_type)
+ {
+ case Variant.Type.Nil:
+ case Variant.Type.Bool:
+ case Variant.Type.Int:
+ case Variant.Type.Float:
+ case Variant.Type.Vector2:
+ case Variant.Type.Vector2i:
+ case Variant.Type.Rect2:
+ case Variant.Type.Rect2i:
+ case Variant.Type.Vector3:
+ case Variant.Type.Vector3i:
+ case Variant.Type.Plane:
+ case Variant.Type.Quaternion:
+ case Variant.Type.Color:
+ case Variant.Type.Rid:
+ return;
+ }
+
+ NativeFuncs.godotsharp_variant_destroy(ref this);
+ _type = Variant.Type.Nil;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_string : IDisposable
+ {
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_string_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_string_name : IDisposable
+ {
+ internal IntPtr _data;
+
+ public void Dispose()
+ {
+ if (_data == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_string_name_destroy(ref this);
+ _data = IntPtr.Zero;
+ }
+
+ // An static method because an instance method could result in a hidden copy if called on an `in` parameter.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsEmpty(in godot_string_name name) =>
+ // This is all that's needed to check if it's empty. Equivalent to `== StringName()` in C++.
+ name._data == IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_node_path : IDisposable
+ {
+ internal IntPtr _data;
+
+ public void Dispose()
+ {
+ if (_data == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_node_path_destroy(ref this);
+ _data = IntPtr.Zero;
+ }
+
+ // An static method because an instance method could result in a hidden copy if called on an `in` parameter.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsEmpty(in godot_node_path nodePath) =>
+ // This is all that's needed to check if it's empty. It's what the `is_empty()` C++ method does.
+ nodePath._data == IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_signal : IDisposable
+ {
+ [FieldOffset(0)] public godot_string_name _name;
+
+ // There's padding here on 32-bit
+
+ [FieldOffset(8)] public UInt64 _objectId;
+
+ public void Dispose()
+ {
+ if (_name._data == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_signal_destroy(ref this);
+ _name._data = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_callable : IDisposable
+ {
+ [FieldOffset(0)] public godot_string_name _method;
+
+ // There's padding here on 32-bit
+
+ [FieldOffset(8)] public UInt64 _objectId;
+ [FieldOffset(8)] public IntPtr _custom;
+
+ public void Dispose()
+ {
+ if (_method._data == IntPtr.Zero && _custom == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_callable_destroy(ref this);
+ _method._data = IntPtr.Zero;
+ _custom = IntPtr.Zero;
+ }
+ }
+
+ // A correctly constructed value needs to call the native default constructor to allocate `_p`.
+ // Don't pass a C# default constructed `godot_array` to native code, unless it's going to
+ // be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_array : IDisposable
+ {
+ internal IntPtr _p;
+
+ public void Dispose()
+ {
+ if (_p == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_array_destroy(ref this);
+ _p = IntPtr.Zero;
+ }
+ }
+
+ // IMPORTANT:
+ // A correctly constructed value needs to call the native default constructor to allocate `_p`.
+ // Don't pass a C# default constructed `godot_dictionary` to native code, unless it's going to
+ // be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_dictionary : IDisposable
+ {
+ internal IntPtr _p;
+
+ public void Dispose()
+ {
+ if (_p == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_dictionary_destroy(ref this);
+ _p = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_byte_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_byte_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_int32_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_int32_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_int64_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_int64_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_float32_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_float32_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_float64_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_float64_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_string_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_string_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_vector2_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_vector2_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_vector3_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_vector3_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ // ReSharper disable once InconsistentNaming
+ internal struct godot_packed_color_array : IDisposable
+ {
+ internal IntPtr _writeProxy;
+ internal IntPtr _ptr;
+
+ public void Dispose()
+ {
+ if (_ptr == IntPtr.Zero)
+ return;
+ NativeFuncs.godotsharp_packed_color_array_destroy(ref this);
+ _ptr = IntPtr.Zero;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs
new file mode 100644
index 0000000000..08d49bb937
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Godot.NativeInterop
+{
+ internal static class InteropUtils
+ {
+ public static Object UnmanagedGetManaged(IntPtr unmanaged)
+ {
+ // TODO: Move to C#
+ return internal_unmanaged_get_managed(unmanaged);
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern Object internal_unmanaged_get_managed(IntPtr unmanaged);
+
+ public static void TieManagedToUnmanaged(Object managed, IntPtr unmanaged)
+ {
+ // TODO: Move to C#
+ internal_tie_managed_to_unmanaged(managed, unmanaged);
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern void internal_tie_managed_to_unmanaged(Object managed, IntPtr unmanaged);
+
+ public static unsafe Object EngineGetSingleton(string name)
+ {
+ using godot_string src = Marshaling.mono_string_to_godot(name);
+ return UnmanagedGetManaged(NativeFuncs.godotsharp_engine_get_singleton(&src));
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
new file mode 100644
index 0000000000..9b6f9633d1
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -0,0 +1,1370 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// ReSharper disable InconsistentNaming
+
+namespace Godot.NativeInterop
+{
+ // We want to use full name qualifiers here even if redundant for clarity
+ [SuppressMessage("ReSharper", "RedundantNameQualifier")]
+ internal static class Marshaling
+ {
+ public static unsafe void SetFieldValue(FieldInfo fieldInfo, object obj, godot_variant* value)
+ {
+ var valueObj = variant_to_mono_object_of_type(value, fieldInfo.FieldType);
+ fieldInfo.SetValue(obj, valueObj);
+ }
+
+ public static Variant.Type managed_to_variant_type(Type type, ref bool r_nil_is_variant)
+ {
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.Boolean:
+ return Variant.Type.Bool;
+ case TypeCode.Char:
+ return Variant.Type.Int;
+ case TypeCode.SByte:
+ return Variant.Type.Int;
+ case TypeCode.Int16:
+ return Variant.Type.Int;
+ case TypeCode.Int32:
+ return Variant.Type.Int;
+ case TypeCode.Int64:
+ return Variant.Type.Int;
+ case TypeCode.Byte:
+ return Variant.Type.Int;
+ case TypeCode.UInt16:
+ return Variant.Type.Int;
+ case TypeCode.UInt32:
+ return Variant.Type.Int;
+ case TypeCode.UInt64:
+ return Variant.Type.Int;
+ case TypeCode.Single:
+ return Variant.Type.Float;
+ case TypeCode.Double:
+ return Variant.Type.Float;
+ case TypeCode.String:
+ return Variant.Type.String;
+ default:
+ {
+ if (type == typeof(Vector2))
+ return Variant.Type.Vector2;
+
+ if (type == typeof(Vector2i))
+ return Variant.Type.Vector2i;
+
+ if (type == typeof(Rect2))
+ return Variant.Type.Rect2;
+
+ if (type == typeof(Rect2i))
+ return Variant.Type.Rect2i;
+
+ if (type == typeof(Transform2D))
+ return Variant.Type.Transform2d;
+
+ if (type == typeof(Vector3))
+ return Variant.Type.Vector3;
+
+ if (type == typeof(Vector3i))
+ return Variant.Type.Vector3i;
+
+ if (type == typeof(Vector4))
+ return Variant.Type.Vector4;
+
+ if (type == typeof(Vector4i))
+ return Variant.Type.Vector4i;
+
+ if (type == typeof(Basis))
+ return Variant.Type.Basis;
+
+ if (type == typeof(Quaternion))
+ return Variant.Type.Quaternion;
+
+ if (type == typeof(Transform3D))
+ return Variant.Type.Transform3d;
+
+ if (type == typeof(Projection))
+ return Variant.Type.Projection;
+
+ if (type == typeof(AABB))
+ return Variant.Type.Aabb;
+
+ if (type == typeof(Color))
+ return Variant.Type.Color;
+
+ if (type == typeof(Plane))
+ return Variant.Type.Plane;
+
+ if (type == typeof(Callable))
+ return Variant.Type.Callable;
+
+ if (type == typeof(SignalInfo))
+ return Variant.Type.Signal;
+
+ if (type.IsEnum)
+ return Variant.Type.Int;
+
+ if (type.IsArray || type.IsSZArray)
+ {
+ if (type == typeof(Byte[]))
+ return Variant.Type.PackedByteArray;
+
+ if (type == typeof(Int32[]))
+ return Variant.Type.PackedInt32Array;
+
+ if (type == typeof(Int64[]))
+ return Variant.Type.PackedInt64Array;
+
+ if (type == typeof(float[]))
+ return Variant.Type.PackedFloat32Array;
+
+ if (type == typeof(double[]))
+ return Variant.Type.PackedFloat64Array;
+
+ if (type == typeof(string[]))
+ return Variant.Type.PackedStringArray;
+
+ if (type == typeof(Vector2[]))
+ return Variant.Type.PackedVector2Array;
+
+ if (type == typeof(Vector3[]))
+ return Variant.Type.PackedVector3Array;
+
+ if (type == typeof(Color[]))
+ return Variant.Type.PackedColorArray;
+
+ if (typeof(Godot.Object[]).IsAssignableFrom(type))
+ return Variant.Type.Array;
+
+ if (type == typeof(object[]))
+ return Variant.Type.Array;
+ }
+ else if (type.IsGenericType)
+ {
+ var genericTypeDefinition = type.GetGenericTypeDefinition();
+
+ if (genericTypeDefinition == typeof(Collections.Dictionary<,>))
+ return Variant.Type.Dictionary;
+
+ if (genericTypeDefinition == typeof(Collections.Array<>))
+ return Variant.Type.Array;
+
+ if (genericTypeDefinition == typeof(System.Collections.Generic.Dictionary<,>))
+ return Variant.Type.Dictionary;
+
+ if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
+ return Variant.Type.Array;
+
+ if (genericTypeDefinition == typeof(IDictionary<,>))
+ return Variant.Type.Dictionary;
+
+ if (genericTypeDefinition == typeof(ICollection<>) || genericTypeDefinition == typeof(IEnumerable<>))
+ return Variant.Type.Array;
+ }
+ else if (type == typeof(object))
+ {
+ r_nil_is_variant = true;
+ return Variant.Type.Nil;
+ }
+ else
+ {
+ if (typeof(Godot.Object).IsAssignableFrom(type))
+ return Variant.Type.Object;
+
+ if (typeof(StringName) == type)
+ return Variant.Type.StringName;
+
+ if (typeof(NodePath) == type)
+ return Variant.Type.NodePath;
+
+ if (typeof(RID) == type)
+ return Variant.Type.Rid;
+
+ if (typeof(Collections.Dictionary) == type || typeof(System.Collections.IDictionary) == type)
+ return Variant.Type.Dictionary;
+
+ if (typeof(Collections.Array) == type ||
+ typeof(System.Collections.ICollection) == type ||
+ typeof(System.Collections.IEnumerable) == type)
+ {
+ return Variant.Type.Array;
+ }
+ }
+
+ break;
+ }
+ }
+
+ r_nil_is_variant = false;
+
+ // Unknown
+ return Variant.Type.Nil;
+ }
+
+ public static bool try_get_array_element_type(Type p_array_type, out Type r_elem_type)
+ {
+ if (p_array_type.IsArray || p_array_type.IsSZArray)
+ {
+ r_elem_type = p_array_type.GetElementType();
+ return true;
+ }
+ else if (p_array_type.IsGenericType)
+ {
+ var genericTypeDefinition = p_array_type.GetGenericTypeDefinition();
+
+ if (typeof(Collections.Array) == genericTypeDefinition ||
+ typeof(System.Collections.Generic.List<>) == genericTypeDefinition ||
+ typeof(System.Collections.ICollection) == genericTypeDefinition ||
+ typeof(System.Collections.IEnumerable) == genericTypeDefinition)
+ {
+ r_elem_type = p_array_type.GetGenericArguments()[0];
+ return true;
+ }
+ }
+
+ r_elem_type = null;
+ return false;
+ }
+
+ /* TODO: Reflection and type checking each time is slow. This will be replaced with source generators. */
+
+ public static godot_variant mono_object_to_variant(object p_obj)
+ {
+ return mono_object_to_variant_impl(p_obj);
+ }
+
+ public static godot_variant mono_object_to_variant_no_err(object p_obj)
+ {
+ return mono_object_to_variant_impl(p_obj);
+ }
+
+ // TODO: Only called from C++. Remove once no longer needed.
+ private static unsafe void mono_object_to_variant_out(object p_obj, bool p_fail_with_err, godot_variant* r_ret)
+ => *r_ret = mono_object_to_variant_impl(p_obj, p_fail_with_err);
+
+ private static unsafe godot_variant mono_object_to_variant_impl(object p_obj, bool p_fail_with_err = true)
+ {
+ if (p_obj == null)
+ return new godot_variant();
+
+ switch (p_obj)
+ {
+ case bool @bool:
+ return VariantUtils.CreateFromBool(@bool);
+ case char @char:
+ return VariantUtils.CreateFromInt(@char);
+ case SByte @int8:
+ return VariantUtils.CreateFromInt(@int8);
+ case Int16 @int16:
+ return VariantUtils.CreateFromInt(@int16);
+ case Int32 @int32:
+ return VariantUtils.CreateFromInt(@int32);
+ case Int64 @int64:
+ return VariantUtils.CreateFromInt(@int64);
+ case Byte @uint8:
+ return VariantUtils.CreateFromInt(@uint8);
+ case UInt16 @uint16:
+ return VariantUtils.CreateFromInt(@uint16);
+ case UInt32 @uint32:
+ return VariantUtils.CreateFromInt(@uint32);
+ case UInt64 @uint64:
+ return VariantUtils.CreateFromInt(@uint64);
+ case float @float:
+ return VariantUtils.CreateFromFloat(@float);
+ case double @double:
+ return VariantUtils.CreateFromFloat(@double);
+ case Vector2 @vector2:
+ return VariantUtils.CreateFromVector2(@vector2);
+ case Vector2i @vector2i:
+ return VariantUtils.CreateFromVector2i(@vector2i);
+ case Rect2 @rect2:
+ return VariantUtils.CreateFromRect2(@rect2);
+ case Rect2i @rect2i:
+ return VariantUtils.CreateFromRect2i(@rect2i);
+ case Transform2D @transform2D:
+ return VariantUtils.CreateFromTransform2D(@transform2D);
+ case Vector3 @vector3:
+ return VariantUtils.CreateFromVector3(@vector3);
+ case Vector3i @vector3i:
+ return VariantUtils.CreateFromVector3i(@vector3i);
+ case Vector4 @vector4:
+ return VariantUtils.CreateFromVector4(@vector4);
+ case Vector4i @vector4i:
+ return VariantUtils.CreateFromVector4i(@vector4i);
+ case Basis @basis:
+ return VariantUtils.CreateFromBasis(@basis);
+ case Quaternion @quaternion:
+ return VariantUtils.CreateFromQuaternion(@quaternion);
+ case Transform3D @transform3d:
+ return VariantUtils.CreateFromTransform3D(@transform3d);
+ case Projection @projection:
+ return VariantUtils.CreateFromProjection(@projection);
+ case AABB @aabb:
+ return VariantUtils.CreateFromAABB(@aabb);
+ case Color @color:
+ return VariantUtils.CreateFromColor(@color);
+ case Plane @plane:
+ return VariantUtils.CreateFromPlane(@plane);
+ case Callable @callable:
+ return VariantUtils.CreateFromCallableTakingOwnershipOfDisposableValue(
+ ConvertCallableToNative(ref @callable));
+ case SignalInfo @signalInfo:
+ return VariantUtils.CreateFromSignalTakingOwnershipOfDisposableValue(
+ ConvertSignalToNative(ref @signalInfo));
+ case Enum @enum:
+ return VariantUtils.CreateFromInt(Convert.ToInt64(@enum));
+ case string @string:
+ {
+ return VariantUtils.CreateFromStringTakingOwnershipOfDisposableValue(
+ mono_string_to_godot(@string));
+ }
+ case Byte[] byteArray:
+ {
+ using godot_packed_byte_array array = mono_array_to_PackedByteArray(byteArray);
+ return VariantUtils.CreateFromPackedByteArray(&array);
+ }
+ case Int32[] int32Array:
+ {
+ using godot_packed_int32_array array = mono_array_to_PackedInt32Array(int32Array);
+ return VariantUtils.CreateFromPackedInt32Array(&array);
+ }
+ case Int64[] int64Array:
+ {
+ using godot_packed_int64_array array = mono_array_to_PackedInt64Array(int64Array);
+ return VariantUtils.CreateFromPackedInt64Array(&array);
+ }
+ case float[] floatArray:
+ {
+ using godot_packed_float32_array array = mono_array_to_PackedFloat32Array(floatArray);
+ return VariantUtils.CreateFromPackedFloat32Array(&array);
+ }
+ case double[] doubleArray:
+ {
+ using godot_packed_float64_array array = mono_array_to_PackedFloat64Array(doubleArray);
+ return VariantUtils.CreateFromPackedFloat64Array(&array);
+ }
+ case string[] stringArray:
+ {
+ using godot_packed_string_array array = mono_array_to_PackedStringArray(stringArray);
+ return VariantUtils.CreateFromPackedStringArray(&array);
+ }
+ case Vector2[] vector2Array:
+ {
+ using godot_packed_vector2_array array = mono_array_to_PackedVector2Array(vector2Array);
+ return VariantUtils.CreateFromPackedVector2Array(&array);
+ }
+ case Vector3[] vector3Array:
+ {
+ using godot_packed_vector3_array array = mono_array_to_PackedVector3Array(vector3Array);
+ return VariantUtils.CreateFromPackedVector3Array(&array);
+ }
+ case Color[] colorArray:
+ {
+ using godot_packed_color_array array = mono_array_to_PackedColorArray(colorArray);
+ return VariantUtils.CreateFromPackedColorArray(&array);
+ }
+ case Godot.Object[] godotObjectArray:
+ {
+ // ReSharper disable once CoVariantArrayConversion
+ using godot_array array = mono_array_to_Array(godotObjectArray);
+ return VariantUtils.CreateFromArray(&array);
+ }
+ case object[] objectArray: // Last one to avoid catching others like string[] and Godot.Object[]
+ {
+ // The pattern match for `object[]` catches arrays on any reference type,
+ // so we need to check the actual type to make sure it's truly `object[]`.
+ if (objectArray.GetType() == typeof(object[]))
+ {
+ using godot_array array = mono_array_to_Array(objectArray);
+ return VariantUtils.CreateFromArray(&array);
+ }
+
+ if (p_fail_with_err)
+ {
+ GD.PushError("Attempted to convert a managed array of unmarshallable element type to Variant.");
+ return new godot_variant();
+ }
+ else
+ {
+ return new godot_variant();
+ }
+ }
+ case Godot.Object godotObject:
+ return VariantUtils.CreateFromGodotObject(godotObject.NativeInstance);
+ case StringName stringName:
+ return VariantUtils.CreateFromStringName(ref stringName.NativeValue);
+ case NodePath nodePath:
+ return VariantUtils.CreateFromNodePath(ref nodePath.NativeValue);
+ case RID rid:
+ return VariantUtils.CreateFromRID(rid);
+ case Collections.Dictionary godotDictionary:
+ return VariantUtils.CreateFromDictionary(godotDictionary.NativeValue);
+ case Collections.Array godotArray:
+ return VariantUtils.CreateFromArray(godotArray.NativeValue);
+ case Collections.IGenericGodotDictionary genericGodotDictionary:
+ {
+ var godotDict = genericGodotDictionary.UnderlyingDictionary;
+ if (godotDict == null)
+ return new godot_variant();
+ return VariantUtils.CreateFromDictionary(godotDict.NativeValue);
+ }
+ case Collections.IGenericGodotArray genericGodotArray:
+ {
+ var godotArray = genericGodotArray.UnderlyingArray;
+ if (godotArray == null)
+ return new godot_variant();
+ return VariantUtils.CreateFromArray(godotArray.NativeValue);
+ }
+ default:
+ {
+ var type = p_obj.GetType();
+
+ if (type.IsGenericType)
+ {
+ var genericTypeDefinition = type.GetGenericTypeDefinition();
+
+ if (genericTypeDefinition == typeof(System.Collections.Generic.Dictionary<,>))
+ {
+ // TODO: Validate key and value types are compatible with Variant
+#if NET
+ Collections.IGenericGodotDictionary genericGodotDictionary = IDictionaryToGenericGodotDictionary((dynamic)p_obj);
+#else
+ var genericArguments = type.GetGenericArguments();
+
+ // With .NET Standard we need a package reference for Microsoft.CSharp in order to
+ // use dynamic, so we have this workaround for now until we switch to .NET 5/6.
+ var method = typeof(Marshaling).GetMethod(nameof(IDictionaryToGenericGodotDictionary),
+ BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly)!
+ .MakeGenericMethod(genericArguments[0], genericArguments[1]);
+
+ var genericGodotDictionary = (Collections.IGenericGodotDictionary)method
+ .Invoke(null, new[] {p_obj});
+#endif
+
+ var godotDict = genericGodotDictionary.UnderlyingDictionary;
+ if (godotDict == null)
+ return new godot_variant();
+ return VariantUtils.CreateFromDictionary(godotDict.NativeValue);
+ }
+
+ if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
+ {
+ // TODO: Validate element type is compatible with Variant
+#if NET
+ var nativeGodotArray = mono_array_to_Array(System.Runtime.InteropServices.CollectionsMarshal.AsSpan((dynamic)p_obj));
+#else
+ // With .NET Standard we need a package reference for Microsoft.CSharp in order to
+ // use dynamic, so we have this workaround for now until we switch to .NET 5/6.
+ // Also CollectionsMarshal.AsSpan is not available with .NET Standard.
+
+ var collection = (System.Collections.ICollection)p_obj;
+ var array = new object[collection.Count];
+ collection.CopyTo(array, 0);
+ var nativeGodotArray = mono_array_to_Array(array);
+#endif
+ return VariantUtils.CreateFromArray(&nativeGodotArray);
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (p_fail_with_err)
+ {
+ GD.PushError("Attempted to convert an unmarshallable managed type to Variant. Name: '" +
+ p_obj.GetType().FullName + ".");
+ return new godot_variant();
+ }
+ else
+ {
+ return new godot_variant();
+ }
+ }
+
+ private static Collections.Dictionary<TKey, TValue> IDictionaryToGenericGodotDictionary<TKey, TValue>
+ (IDictionary<TKey, TValue> dictionary) => new(dictionary);
+
+ public static unsafe string variant_to_mono_string(godot_variant* p_var)
+ {
+ switch ((*p_var)._type)
+ {
+ case Variant.Type.Nil:
+ return null; // Otherwise, Variant -> String would return the string "Null"
+ case Variant.Type.String:
+ {
+ // We avoid the internal call if the stored type is the same we want.
+ return mono_string_from_godot(&(*p_var)._data._m_string);
+ }
+ default:
+ {
+ using godot_string godotString = NativeFuncs.godotsharp_variant_as_string(p_var);
+ return mono_string_from_godot(&godotString);
+ }
+ }
+ }
+
+ public static unsafe object variant_to_mono_object_of_type(godot_variant* p_var, Type type)
+ {
+ // This function is only needed to set the value of properties. Fields have their own implementation, set_value_from_variant.
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.Boolean:
+ return VariantUtils.ConvertToBool(p_var);
+ case TypeCode.Char:
+ return VariantUtils.ConvertToChar(p_var);
+ case TypeCode.SByte:
+ return VariantUtils.ConvertToInt8(p_var);
+ case TypeCode.Int16:
+ return VariantUtils.ConvertToInt16(p_var);
+ case TypeCode.Int32:
+ return VariantUtils.ConvertToInt32(p_var);
+ case TypeCode.Int64:
+ return VariantUtils.ConvertToInt64(p_var);
+ case TypeCode.Byte:
+ return VariantUtils.ConvertToUInt8(p_var);
+ case TypeCode.UInt16:
+ return VariantUtils.ConvertToUInt16(p_var);
+ case TypeCode.UInt32:
+ return VariantUtils.ConvertToUInt32(p_var);
+ case TypeCode.UInt64:
+ return VariantUtils.ConvertToUInt64(p_var);
+ case TypeCode.Single:
+ return VariantUtils.ConvertToFloat32(p_var);
+ case TypeCode.Double:
+ return VariantUtils.ConvertToFloat64(p_var);
+ case TypeCode.String:
+ return variant_to_mono_string(p_var);
+ default:
+ {
+ if (type == typeof(Vector2))
+ return VariantUtils.ConvertToVector2(p_var);
+
+ if (type == typeof(Vector2i))
+ return VariantUtils.ConvertToVector2i(p_var);
+
+ if (type == typeof(Rect2))
+ return VariantUtils.ConvertToRect2(p_var);
+
+ if (type == typeof(Rect2i))
+ return VariantUtils.ConvertToRect2i(p_var);
+
+ if (type == typeof(Transform2D))
+ return VariantUtils.ConvertToTransform2D(p_var);
+
+ if (type == typeof(Vector3))
+ return VariantUtils.ConvertToVector3(p_var);
+
+ if (type == typeof(Vector3i))
+ return VariantUtils.ConvertToVector3i(p_var);
+
+ if (type == typeof(Vector4))
+ return VariantUtils.ConvertToVector4(p_var);
+
+ if (type == typeof(Vector4i))
+ return VariantUtils.ConvertToVector4i(p_var);
+
+ if (type == typeof(Basis))
+ return VariantUtils.ConvertToBasis(p_var);
+
+ if (type == typeof(Quaternion))
+ return VariantUtils.ConvertToQuaternion(p_var);
+
+ if (type == typeof(Transform3D))
+ return VariantUtils.ConvertToTransform3D(p_var);
+
+ if (type == typeof(Projection))
+ return VariantUtils.ConvertToProjection(p_var);
+
+ if (type == typeof(AABB))
+ return VariantUtils.ConvertToAABB(p_var);
+
+ if (type == typeof(Color))
+ return VariantUtils.ConvertToColor(p_var);
+
+ if (type == typeof(Plane))
+ return VariantUtils.ConvertToPlane(p_var);
+
+ if (type == typeof(Callable))
+ {
+ using godot_callable callable = NativeFuncs.godotsharp_variant_as_callable(p_var);
+ return ConvertCallableToManaged(&callable);
+ }
+
+ if (type == typeof(SignalInfo))
+ {
+ using godot_signal signal = NativeFuncs.godotsharp_variant_as_signal(p_var);
+ return ConvertSignalToManaged(&signal);
+ }
+
+ if (type.IsEnum)
+ {
+ var enumUnderlyingType = type.GetEnumUnderlyingType();
+ switch (Type.GetTypeCode(enumUnderlyingType))
+ {
+ case TypeCode.SByte:
+ return VariantUtils.ConvertToInt8(p_var);
+ case TypeCode.Int16:
+ return VariantUtils.ConvertToInt16(p_var);
+ case TypeCode.Int32:
+ return VariantUtils.ConvertToInt32(p_var);
+ case TypeCode.Int64:
+ return VariantUtils.ConvertToInt64(p_var);
+ case TypeCode.Byte:
+ return VariantUtils.ConvertToUInt8(p_var);
+ case TypeCode.UInt16:
+ return VariantUtils.ConvertToUInt16(p_var);
+ case TypeCode.UInt32:
+ return VariantUtils.ConvertToUInt32(p_var);
+ case TypeCode.UInt64:
+ return VariantUtils.ConvertToUInt64(p_var);
+ default:
+ {
+ GD.PushError("Attempted to convert Variant to enum value of unsupported underlying type. Name: " +
+ type.FullName + " : " + enumUnderlyingType.FullName + ".");
+ return null;
+ }
+ }
+ }
+
+ if (type.IsArray || type.IsSZArray)
+ return variant_to_mono_array_of_type(p_var, type);
+ else if (type.IsGenericType)
+ return variant_to_mono_object_of_genericinst(p_var, type);
+ else if (type == typeof(object))
+ return variant_to_mono_object(p_var);
+ if (variant_to_mono_object_of_class(p_var, type, out object res))
+ return res;
+
+ break;
+ }
+ }
+
+ GD.PushError("Attempted to convert Variant to unsupported type. Name: " +
+ type.FullName + ".");
+ return null;
+ }
+
+ private static unsafe object variant_to_mono_array_of_type(godot_variant* p_var, Type type)
+ {
+ if (type == typeof(Byte[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_byte_array(p_var);
+ return PackedByteArray_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(Int32[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int32_array(p_var);
+ return PackedInt32Array_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(Int64[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int64_array(p_var);
+ return PackedInt64Array_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(float[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float32_array(p_var);
+ return PackedFloat32Array_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(double[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float64_array(p_var);
+ return PackedFloat64Array_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(string[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_string_array(p_var);
+ return PackedStringArray_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(Vector2[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector2_array(p_var);
+ return PackedVector2Array_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(Vector3[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector3_array(p_var);
+ return PackedVector3Array_to_mono_array(&packedArray);
+ }
+
+ if (type == typeof(Color[]))
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_color_array(p_var);
+ return PackedColorArray_to_mono_array(&packedArray);
+ }
+
+ 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);
+ }
+
+ if (type == typeof(object[]))
+ {
+ using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
+ return Array_to_mono_array(&godotArray);
+ }
+
+ GD.PushError("Attempted to convert Variant to array of unsupported element type. Name: " +
+ type.GetElementType()!.FullName + ".");
+ return null;
+ }
+
+ private static unsafe bool variant_to_mono_object_of_class(godot_variant* p_var, Type type, out object res)
+ {
+ if (typeof(Godot.Object).IsAssignableFrom(type))
+ {
+ res = InteropUtils.UnmanagedGetManaged(VariantUtils.ConvertToGodotObject(p_var));
+ return true;
+ }
+
+ if (typeof(StringName) == type)
+ {
+ res = StringName.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToStringName(p_var));
+ return true;
+ }
+
+ if (typeof(NodePath) == type)
+ {
+ res = NodePath.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToNodePath(p_var));
+ return true;
+ }
+
+ if (typeof(RID) == type)
+ {
+ res = VariantUtils.ConvertToRID(p_var);
+ return true;
+ }
+
+ if (typeof(Collections.Dictionary) == type || typeof(System.Collections.IDictionary) == type)
+ {
+ res = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToDictionary(p_var));
+ return true;
+ }
+
+ if (typeof(Collections.Array) == type ||
+ typeof(System.Collections.ICollection) == type ||
+ typeof(System.Collections.IEnumerable) == type)
+ {
+ res = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToArray(p_var));
+ return true;
+ }
+
+ res = null;
+ return false;
+ }
+
+ private static unsafe object variant_to_mono_object_of_genericinst(godot_variant* p_var, Type type)
+ {
+ static object variant_to_generic_godot_collections_dictionary(godot_variant* p_var, Type fullType)
+ {
+ var underlyingDict = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToDictionary(p_var));
+ return Activator.CreateInstance(fullType,
+ BindingFlags.Public | BindingFlags.Instance, null,
+ args: new object[] {underlyingDict}, null);
+ }
+
+ static object variant_to_generic_godot_collections_array(godot_variant* p_var, Type fullType)
+ {
+ var underlyingArray = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToArray(p_var));
+ return Activator.CreateInstance(fullType,
+ BindingFlags.Public | BindingFlags.Instance, null,
+ args: new object[] {underlyingArray}, null);
+ }
+
+ var genericTypeDefinition = type.GetGenericTypeDefinition();
+
+ if (genericTypeDefinition == typeof(Collections.Dictionary<,>))
+ return variant_to_generic_godot_collections_dictionary(p_var, type);
+
+ if (genericTypeDefinition == typeof(Collections.Array<>))
+ return variant_to_generic_godot_collections_array(p_var, type);
+
+ if (genericTypeDefinition == typeof(System.Collections.Generic.Dictionary<,>))
+ {
+ using var godotDictionary = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToDictionary(p_var));
+
+ var dictionary = (System.Collections.IDictionary)Activator.CreateInstance(type,
+ BindingFlags.Public | BindingFlags.Instance, null,
+ args: new object[]
+ {
+ /* capacity: */ godotDictionary.Count
+ }, null);
+
+ foreach (System.Collections.DictionaryEntry pair in godotDictionary)
+ dictionary.Add(pair.Key, pair.Value);
+
+ return dictionary;
+ }
+
+ if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
+ {
+ using var godotArray = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ VariantUtils.ConvertToArray(p_var));
+
+ var list = (System.Collections.IList)Activator.CreateInstance(type,
+ BindingFlags.Public | BindingFlags.Instance, null,
+ args: new object[]
+ {
+ /* capacity: */ godotArray.Count
+ }, null);
+
+ foreach (object elem in godotArray)
+ list.Add(elem);
+
+ return list;
+ }
+
+ if (genericTypeDefinition == typeof(IDictionary<,>))
+ {
+ var genericArgs = type.GetGenericArguments();
+ var keyType = genericArgs[0];
+ var valueType = genericArgs[1];
+ var genericGodotDictionaryType = typeof(Collections.Dictionary<,>)
+ .MakeGenericType(keyType, valueType);
+
+ return variant_to_generic_godot_collections_dictionary(p_var, genericGodotDictionaryType);
+ }
+
+ if (genericTypeDefinition == typeof(ICollection<>) || genericTypeDefinition == typeof(IEnumerable<>))
+ {
+ var elementType = type.GetGenericArguments()[0];
+ var genericGodotArrayType = typeof(Collections.Array<>)
+ .MakeGenericType(elementType);
+
+ return variant_to_generic_godot_collections_array(p_var, genericGodotArrayType);
+ }
+
+ return null;
+ }
+
+ public static unsafe object variant_to_mono_object(godot_variant* p_var)
+ {
+ switch ((*p_var)._type)
+ {
+ case Variant.Type.Bool:
+ return (bool)(*p_var)._data._bool;
+ case Variant.Type.Int:
+ return (*p_var)._data._int;
+ case Variant.Type.Float:
+ {
+#if REAL_T_IS_DOUBLE
+ return (*p_var)._data._float;
+#else
+ return (float)(*p_var)._data._float;
+#endif
+ }
+ case Variant.Type.String:
+ return mono_string_from_godot(&(*p_var)._data._m_string);
+ case Variant.Type.Vector2:
+ return (*p_var)._data._m_vector2;
+ case Variant.Type.Vector2i:
+ return (*p_var)._data._m_vector2i;
+ case Variant.Type.Rect2:
+ return (*p_var)._data._m_rect2;
+ case Variant.Type.Rect2i:
+ return (*p_var)._data._m_rect2i;
+ case Variant.Type.Vector3:
+ return (*p_var)._data._m_vector3;
+ case Variant.Type.Vector3i:
+ return (*p_var)._data._m_vector3i;
+ case Variant.Type.Transform2d:
+ return *(*p_var)._data._transform2d;
+ case Variant.Type.Vector4:
+ return *(*p_var)._data._vector4;
+ case Variant.Type.Vector4i:
+ return *(*p_var)._data._vector4i;
+ case Variant.Type.Plane:
+ return (*p_var)._data._m_plane;
+ case Variant.Type.Quaternion:
+ return (*p_var)._data._m_quaternion;
+ case Variant.Type.Aabb:
+ return *(*p_var)._data._aabb;
+ case Variant.Type.Basis:
+ return *(*p_var)._data._basis;
+ case Variant.Type.Transform3d:
+ return *(*p_var)._data._transform3d;
+ case Variant.Type.Projection:
+ return *(*p_var)._data._projection;
+ case Variant.Type.Color:
+ return (*p_var)._data._m_color;
+ case Variant.Type.StringName:
+ {
+ // The Variant owns the value, so we need to make a copy
+ return StringName.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_string_name_new_copy(&(*p_var)._data._m_string_name));
+ }
+ case Variant.Type.NodePath:
+ {
+ // The Variant owns the value, so we need to make a copy
+ return NodePath.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_node_path_new_copy(&(*p_var)._data._m_node_path));
+ }
+ case Variant.Type.Rid:
+ return (*p_var)._data._m_rid;
+ case Variant.Type.Object:
+ return InteropUtils.UnmanagedGetManaged((*p_var)._data._m_obj_data.obj);
+ case Variant.Type.Callable:
+ return ConvertCallableToManaged(&(*p_var)._data._m_callable);
+ case Variant.Type.Signal:
+ return ConvertSignalToManaged(&(*p_var)._data._m_signal);
+ case Variant.Type.Dictionary:
+ {
+ // The Variant owns the value, so we need to make a copy
+ return Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_dictionary_new_copy(&(*p_var)._data._m_dictionary));
+ }
+ case Variant.Type.Array:
+ {
+ // The Variant owns the value, so we need to make a copy
+ return Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_array_new_copy(&(*p_var)._data._m_array));
+ }
+ case Variant.Type.PackedByteArray:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_byte_array(p_var);
+ return PackedByteArray_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedInt32Array:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int32_array(p_var);
+ return PackedInt32Array_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedInt64Array:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int64_array(p_var);
+ return PackedInt64Array_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedFloat32Array:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float32_array(p_var);
+ return PackedFloat32Array_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedFloat64Array:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float64_array(p_var);
+ return PackedFloat64Array_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedStringArray:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_string_array(p_var);
+ return PackedStringArray_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedVector2Array:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector2_array(p_var);
+ return PackedVector2Array_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedVector3Array:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector3_array(p_var);
+ return PackedVector3Array_to_mono_array(&packedArray);
+ }
+ case Variant.Type.PackedColorArray:
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_color_array(p_var);
+ return PackedColorArray_to_mono_array(&packedArray);
+ }
+ default:
+ return null;
+ }
+ }
+
+ // String
+
+ public static unsafe godot_string mono_string_to_godot(string p_mono_string)
+ {
+ if (p_mono_string == null)
+ return new godot_string();
+
+ fixed (char* methodChars = p_mono_string)
+ {
+ godot_string dest;
+ NativeFuncs.godotsharp_string_new_with_utf16_chars(&dest, methodChars);
+ return dest;
+ }
+ }
+
+ public static unsafe string mono_string_from_godot(godot_string* p_string)
+ {
+ if ((*p_string)._ptr == IntPtr.Zero)
+ return string.Empty;
+
+ const int sizeOfChar32 = 4;
+ byte* bytes = (byte*)(*p_string)._ptr;
+ int size = *((int*)(*p_string)._ptr - 1);
+ if (size == 0)
+ return string.Empty;
+ size -= 1; // zero at the end
+ int sizeInBytes = size * sizeOfChar32;
+ return System.Text.Encoding.UTF32.GetString(bytes, sizeInBytes);
+ }
+
+ // Callable
+
+ public static godot_callable ConvertCallableToNative(ref Callable p_managed_callable)
+ {
+ if (p_managed_callable.Delegate != null)
+ {
+ unsafe
+ {
+ godot_callable callable;
+ NativeFuncs.godotsharp_callable_new_with_delegate(
+ GCHandle.ToIntPtr(GCHandle.Alloc(p_managed_callable.Delegate)), &callable);
+ return callable;
+ }
+ }
+ else
+ {
+ unsafe
+ {
+ godot_string_name method;
+
+ if (p_managed_callable.Method != null && !p_managed_callable.Method.IsEmpty)
+ {
+ godot_string_name src = p_managed_callable.Method.NativeValue;
+ method = NativeFuncs.godotsharp_string_name_new_copy(&src);
+ }
+ else
+ {
+ method = default;
+ }
+
+ return new godot_callable
+ {
+ _method = method, // Takes ownership of disposable
+ _objectId = p_managed_callable.Target.GetInstanceId()
+ };
+ }
+ }
+ }
+
+ public static unsafe Callable ConvertCallableToManaged(godot_callable* p_callable)
+ {
+ IntPtr delegateGCHandle;
+ IntPtr godotObject;
+ godot_string_name name;
+
+ if (NativeFuncs.godotsharp_callable_get_data_for_marshalling(
+ p_callable, &delegateGCHandle, &godotObject, &name))
+ {
+ if (delegateGCHandle != IntPtr.Zero)
+ {
+ return new Callable((Delegate)GCHandle.FromIntPtr(delegateGCHandle).Target);
+ }
+ else
+ {
+ return new Callable(
+ InteropUtils.UnmanagedGetManaged(godotObject),
+ StringName.CreateTakingOwnershipOfDisposableValue(name));
+ }
+ }
+
+ // Some other unsupported callable
+ return new Callable();
+ }
+
+ // SignalInfo
+
+ public static godot_signal ConvertSignalToNative(ref SignalInfo p_managed_signal)
+ {
+ ulong ownerId = p_managed_signal.Owner.GetInstanceId();
+ unsafe
+ {
+ godot_string_name name;
+
+ if (p_managed_signal.Name != null && !p_managed_signal.Name.IsEmpty)
+ {
+ godot_string_name src = p_managed_signal.Name.NativeValue;
+ name = NativeFuncs.godotsharp_string_name_new_copy(&src);
+ }
+ else
+ {
+ name = default;
+ }
+
+ return new godot_signal()
+ {
+ _name = name,
+ _objectId = ownerId
+ };
+ }
+ }
+
+ public static unsafe SignalInfo ConvertSignalToManaged(godot_signal* p_signal)
+ {
+ var owner = GD.InstanceFromId((*p_signal)._objectId);
+ var name = StringName.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_string_name_new_copy(&(*p_signal)._name));
+ return new SignalInfo(owner, name);
+ }
+
+ // Array
+
+ public static unsafe object[] Array_to_mono_array(godot_array* p_array)
+ {
+ var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_array_new_copy(p_array));
+
+ int length = array.Count;
+ var ret = new object[length];
+
+ array.CopyTo(ret, 0); // variant_to_mono_object handled by Collections.Array
+
+ return ret;
+ }
+
+ public static unsafe object Array_to_mono_array_of_type(godot_array* p_array, Type type)
+ {
+ var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_array_new_copy(p_array));
+
+ int length = array.Count;
+ object ret = Activator.CreateInstance(type, length);
+
+ array.CopyTo((object[])ret, 0); // variant_to_mono_object handled by Collections.Array
+
+ return ret;
+ }
+
+ public static godot_array mono_array_to_Array(Span<object> p_array)
+ {
+ if (p_array.IsEmpty)
+ {
+ godot_array ret;
+ Collections.Array.godot_icall_Array_Ctor(out ret);
+ return ret;
+ }
+
+ using var array = new Collections.Array();
+ array.Resize(p_array.Length);
+
+ for (int i = 0; i < p_array.Length; i++)
+ array[i] = p_array[i];
+
+ godot_array src = array.NativeValue;
+ unsafe
+ {
+ return NativeFuncs.godotsharp_array_new_copy(&src);
+ }
+ }
+
+ // PackedByteArray
+
+ public static unsafe byte[] PackedByteArray_to_mono_array(godot_packed_byte_array* p_array)
+ {
+ byte* buffer = (byte*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ var array = new byte[size];
+ fixed (byte* dest = array)
+ Buffer.MemoryCopy(buffer, dest, size, size);
+ return array;
+ }
+
+ public static unsafe godot_packed_byte_array mono_array_to_PackedByteArray(Span<byte> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_byte_array();
+ fixed (byte* src = p_array)
+ return NativeFuncs.godotsharp_packed_byte_array_new_mem_copy(src, p_array.Length);
+ }
+
+ // PackedInt32Array
+
+ public static unsafe int[] PackedInt32Array_to_mono_array(godot_packed_int32_array* p_array)
+ {
+ int* buffer = (int*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ int sizeInBytes = size * sizeof(int);
+ var array = new int[size];
+ fixed (int* dest = array)
+ Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes);
+ return array;
+ }
+
+ public static unsafe godot_packed_int32_array mono_array_to_PackedInt32Array(Span<int> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_int32_array();
+ fixed (int* src = p_array)
+ return NativeFuncs.godotsharp_packed_int32_array_new_mem_copy(src, p_array.Length);
+ }
+
+ // PackedInt64Array
+
+ public static unsafe long[] PackedInt64Array_to_mono_array(godot_packed_int64_array* p_array)
+ {
+ long* buffer = (long*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ int sizeInBytes = size * sizeof(long);
+ var array = new long[size];
+ fixed (long* dest = array)
+ Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes);
+ return array;
+ }
+
+ public static unsafe godot_packed_int64_array mono_array_to_PackedInt64Array(Span<long> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_int64_array();
+ fixed (long* src = p_array)
+ return NativeFuncs.godotsharp_packed_int64_array_new_mem_copy(src, p_array.Length);
+ }
+
+ // PackedFloat32Array
+
+ public static unsafe float[] PackedFloat32Array_to_mono_array(godot_packed_float32_array* p_array)
+ {
+ float* buffer = (float*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ int sizeInBytes = size * sizeof(float);
+ var array = new float[size];
+ fixed (float* dest = array)
+ Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes);
+ return array;
+ }
+
+ public static unsafe godot_packed_float32_array mono_array_to_PackedFloat32Array(Span<float> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_float32_array();
+ fixed (float* src = p_array)
+ return NativeFuncs.godotsharp_packed_float32_array_new_mem_copy(src, p_array.Length);
+ }
+
+ // PackedFloat64Array
+
+ public static unsafe double[] PackedFloat64Array_to_mono_array(godot_packed_float64_array* p_array)
+ {
+ double* buffer = (double*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ int sizeInBytes = size * sizeof(double);
+ var array = new double[size];
+ fixed (double* dest = array)
+ Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes);
+ return array;
+ }
+
+ public static unsafe godot_packed_float64_array mono_array_to_PackedFloat64Array(Span<double> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_float64_array();
+ fixed (double* src = p_array)
+ return NativeFuncs.godotsharp_packed_float64_array_new_mem_copy(src, p_array.Length);
+ }
+
+ // PackedStringArray
+
+ public static unsafe string[] PackedStringArray_to_mono_array(godot_packed_string_array* p_array)
+ {
+ godot_string* buffer = (godot_string*)(*p_array)._ptr;
+ if (buffer == null)
+ return new string[] { };
+ int size = *((int*)(*p_array)._ptr - 1);
+ var array = new string[size];
+ for (int i = 0; i < size; i++)
+ array[i] = mono_string_from_godot(&buffer[i]);
+ return array;
+ }
+
+ public static unsafe godot_packed_string_array mono_array_to_PackedStringArray(Span<string> p_array)
+ {
+ godot_packed_string_array dest = new godot_packed_string_array();
+
+ if (p_array.IsEmpty)
+ return dest;
+
+ /* TODO: Replace godotsharp_packed_string_array_add with a single internal call to
+ get the write address. We can't use `dest._ptr` directly for writing due to COW. */
+
+ for (int i = 0; i < p_array.Length; i++)
+ {
+ using godot_string godotStrElem = mono_string_to_godot(p_array[i]);
+ NativeFuncs.godotsharp_packed_string_array_add(&dest, &godotStrElem);
+ }
+
+ return dest;
+ }
+
+ // PackedVector2Array
+
+ public static unsafe Vector2[] PackedVector2Array_to_mono_array(godot_packed_vector2_array* p_array)
+ {
+ Vector2* buffer = (Vector2*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ int sizeInBytes = size * sizeof(Vector2);
+ var array = new Vector2[size];
+ fixed (Vector2* dest = array)
+ Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes);
+ return array;
+ }
+
+ public static unsafe godot_packed_vector2_array mono_array_to_PackedVector2Array(Span<Vector2> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_vector2_array();
+ fixed (Vector2* src = p_array)
+ return NativeFuncs.godotsharp_packed_vector2_array_new_mem_copy(src, p_array.Length);
+ }
+
+ // PackedVector3Array
+
+ public static unsafe Vector3[] PackedVector3Array_to_mono_array(godot_packed_vector3_array* p_array)
+ {
+ Vector3* buffer = (Vector3*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ int sizeInBytes = size * sizeof(Vector3);
+ var array = new Vector3[size];
+ fixed (Vector3* dest = array)
+ Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes);
+ return array;
+ }
+
+ public static unsafe godot_packed_vector3_array mono_array_to_PackedVector3Array(Span<Vector3> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_vector3_array();
+ fixed (Vector3* src = p_array)
+ return NativeFuncs.godotsharp_packed_vector3_array_new_mem_copy(src, p_array.Length);
+ }
+
+ // PackedColorArray
+
+ public static unsafe Color[] PackedColorArray_to_mono_array(godot_packed_color_array* p_array)
+ {
+ Color* buffer = (Color*)(*p_array)._ptr;
+ int size = *((int*)(*p_array)._ptr - 1);
+ int sizeInBytes = size * sizeof(Color);
+ var array = new Color[size];
+ fixed (Color* dest = array)
+ Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes);
+ return array;
+ }
+
+ public static unsafe godot_packed_color_array mono_array_to_PackedColorArray(Span<Color> p_array)
+ {
+ if (p_array.IsEmpty)
+ return new godot_packed_color_array();
+ fixed (Color* src = p_array)
+ return NativeFuncs.godotsharp_packed_color_array_new_mem_copy(src, p_array.Length);
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
new file mode 100644
index 0000000000..2f1056219d
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
@@ -0,0 +1,346 @@
+using System;
+using System.Runtime.InteropServices;
+
+// ReSharper disable InconsistentNaming
+
+namespace Godot.NativeInterop
+{
+#if !NET
+ // This improves P/Invoke performance.
+ // The attribute is not available with .NET Core and it's not needed there.
+ [System.Security.SuppressUnmanagedCodeSecurity]
+#endif
+ internal static unsafe partial class NativeFuncs
+ {
+ private const string GodotDllName = "__Internal";
+
+ // Custom functions
+
+ [DllImport(GodotDllName)]
+ public static extern IntPtr godotsharp_method_bind_get_method(ref godot_string_name p_classname, char* p_methodname);
+
+#if NET
+ [DllImport(GodotDllName)]
+ public static extern delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(ref godot_string_name p_classname);
+#else
+ // Workaround until we switch to .NET 5/6
+ [DllImport(GodotDllName)]
+ public static extern IntPtr godotsharp_get_class_constructor(ref godot_string_name p_classname);
+
+ [DllImport(GodotDllName)]
+ public static extern IntPtr godotsharp_invoke_class_constructor(IntPtr p_creation_func);
+#endif
+
+ [DllImport(GodotDllName)]
+ public static extern IntPtr godotsharp_engine_get_singleton(godot_string* p_name);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_ref_destroy(ref godot_ref p_instance);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_string_name_new_from_string(godot_string_name* dest, godot_string* name);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_node_path_new_from_string(godot_node_path* dest, godot_string* name);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_string_name_as_string(godot_string* r_dest, godot_string_name* p_name);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_node_path_as_string(godot_string* r_dest, godot_node_path* p_np);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_int32_array godotsharp_packed_int32_array_new_mem_copy(int* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_int64_array godotsharp_packed_int64_array_new_mem_copy(long* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_float32_array godotsharp_packed_float32_array_new_mem_copy(float* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_float64_array godotsharp_packed_float64_array_new_mem_copy(double* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_vector2_array godotsharp_packed_vector2_array_new_mem_copy(Vector2* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_vector3_array godotsharp_packed_vector3_array_new_mem_copy(Vector3* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_color_array godotsharp_packed_color_array_new_mem_copy(Color* p_src, int p_length);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_string_array_add(godot_packed_string_array* r_dest, godot_string* p_element);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, godot_callable* r_callable);
+
+ [DllImport(GodotDllName)]
+ public static extern bool godotsharp_callable_get_data_for_marshalling(godot_callable* p_callable, IntPtr* r_delegate_handle, IntPtr* r_object, godot_string_name* r_name);
+
+ // GDNative functions
+
+ // gdnative.h
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_method_bind_ptrcall(IntPtr p_method_bind, IntPtr p_instance, void** p_args, void* p_ret);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_variant godotsharp_method_bind_call(IntPtr p_method_bind, IntPtr p_instance, godot_variant** p_args, int p_arg_count, godot_variant_call_error* p_call_error);
+
+ // variant.h
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_string_name(godot_variant* r_dest, godot_string_name* p_s);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_node_path(godot_variant* r_dest, godot_node_path* p_np);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_object(godot_variant* r_dest, IntPtr p_obj);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_transform2d(godot_variant* r_dest, Transform2D* p_t2d);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_vector4(godot_variant* r_dest, Vector4* p_vec4);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_vector4i(godot_variant* r_dest, Vector4i* p_vec4i);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_basis(godot_variant* r_dest, Basis* p_basis);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_transform3d(godot_variant* r_dest, Transform3D* p_trans);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_projection(godot_variant* r_dest, Projection* p_proj);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_aabb(godot_variant* r_dest, AABB* p_aabb);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_dictionary(godot_variant* r_dest, godot_dictionary* p_dict);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_array(godot_variant* r_dest, godot_array* p_arr);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_byte_array(godot_variant* r_dest, godot_packed_byte_array* p_pba);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_int32_array(godot_variant* r_dest, godot_packed_int32_array* p_pia);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_int64_array(godot_variant* r_dest, godot_packed_int64_array* p_pia);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_float32_array(godot_variant* r_dest, godot_packed_float32_array* p_pra);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_float64_array(godot_variant* r_dest, godot_packed_float64_array* p_pra);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_string_array(godot_variant* r_dest, godot_packed_string_array* p_psa);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_vector2_array(godot_variant* r_dest, godot_packed_vector2_array* p_pv2a);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_vector3_array(godot_variant* r_dest, godot_packed_vector3_array* p_pv3a);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_new_packed_color_array(godot_variant* r_dest, godot_packed_color_array* p_pca);
+
+ [DllImport(GodotDllName)]
+ public static extern bool godotsharp_variant_as_bool(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Int64 godotsharp_variant_as_int(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern double godotsharp_variant_as_float(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_string godotsharp_variant_as_string(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Vector2 godotsharp_variant_as_vector2(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Vector2i godotsharp_variant_as_vector2i(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Rect2 godotsharp_variant_as_rect2(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Rect2i godotsharp_variant_as_rect2i(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Vector3 godotsharp_variant_as_vector3(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Vector3i godotsharp_variant_as_vector3i(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Transform2D godotsharp_variant_as_transform2d(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Vector4 godotsharp_variant_as_vector4(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Vector4i godotsharp_variant_as_vector4i(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Plane godotsharp_variant_as_plane(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Quaternion godotsharp_variant_as_quaternion(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern AABB godotsharp_variant_as_aabb(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Basis godotsharp_variant_as_basis(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Transform3D godotsharp_variant_as_transform3d(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Projection godotsharp_variant_as_projection(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern Color godotsharp_variant_as_color(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_string_name godotsharp_variant_as_string_name(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_node_path godotsharp_variant_as_node_path(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern RID godotsharp_variant_as_rid(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_callable godotsharp_variant_as_callable(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_signal godotsharp_variant_as_signal(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_dictionary godotsharp_variant_as_dictionary(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_array godotsharp_variant_as_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_byte_array godotsharp_variant_as_packed_byte_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_int32_array godotsharp_variant_as_packed_int32_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_int64_array godotsharp_variant_as_packed_int64_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_float32_array godotsharp_variant_as_packed_float32_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_float64_array godotsharp_variant_as_packed_float64_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_string_array godotsharp_variant_as_packed_string_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(godot_variant* p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern godot_packed_color_array godotsharp_variant_as_packed_color_array(godot_variant* p_self);
+
+ // string.h
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_string_new_with_utf16_chars(godot_string* r_dest, char* p_contents);
+
+ // string_name.h
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_string_name_new_copy(godot_string_name* r_dest, godot_string_name* p_src);
+
+ // node_path.h
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_node_path_new_copy(godot_node_path* r_dest, godot_node_path* p_src);
+
+ // array.h
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_array_new_copy(godot_array* r_dest, godot_array* p_src);
+
+ // dictionary.h
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_dictionary_new_copy(godot_dictionary* r_dest, godot_dictionary* p_src);
+
+ // destroy functions
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_byte_array_destroy(ref godot_packed_byte_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_int32_array_destroy(ref godot_packed_int32_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_int64_array_destroy(ref godot_packed_int64_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_float32_array_destroy(ref godot_packed_float32_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_float64_array_destroy(ref godot_packed_float64_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_string_array_destroy(ref godot_packed_string_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_vector2_array_destroy(ref godot_packed_vector2_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_vector3_array_destroy(ref godot_packed_vector3_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_packed_color_array_destroy(ref godot_packed_color_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_variant_destroy(ref godot_variant p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_string_destroy(ref godot_string p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_string_name_destroy(ref godot_string_name p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_node_path_destroy(ref godot_node_path p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_signal_destroy(ref godot_signal p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_callable_destroy(ref godot_callable p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_array_destroy(ref godot_array p_self);
+
+ [DllImport(GodotDllName)]
+ public static extern void godotsharp_dictionary_destroy(ref godot_dictionary p_self);
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
new file mode 100644
index 0000000000..70df79c1de
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Runtime.CompilerServices;
+
+// ReSharper disable InconsistentNaming
+
+namespace Godot.NativeInterop
+{
+ internal static unsafe partial class NativeFuncs
+ {
+ public static godot_string_name godotsharp_string_name_new_copy(godot_string_name* src)
+ {
+ godot_string_name ret;
+ godotsharp_string_name_new_copy(&ret, src);
+ return ret;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_string_name godotsharp_string_name_new_copy(godot_string_name src)
+ => godotsharp_string_name_new_copy(&src);
+
+ public static godot_node_path godotsharp_node_path_new_copy(godot_node_path* src)
+ {
+ godot_node_path ret;
+ godotsharp_node_path_new_copy(&ret, src);
+ return ret;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_node_path godotsharp_node_path_new_copy(godot_node_path src)
+ => godotsharp_node_path_new_copy(&src);
+
+ public static godot_array godotsharp_array_new_copy(godot_array* src)
+ {
+ godot_array ret;
+ godotsharp_array_new_copy(&ret, src);
+ return ret;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_array godotsharp_array_new_copy(godot_array src)
+ => godotsharp_array_new_copy(&src);
+
+ public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary* src)
+ {
+ godot_dictionary ret;
+ godotsharp_dictionary_new_copy(&ret, src);
+ return ret;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary src)
+ => godotsharp_dictionary_new_copy(&src);
+
+ public static godot_string_name godotsharp_string_name_new_from_string(string name)
+ {
+ godot_string_name ret;
+ using godot_string src = Marshaling.mono_string_to_godot(name);
+ godotsharp_string_name_new_from_string(&ret, &src);
+ return ret;
+ }
+
+ public static godot_node_path godotsharp_node_path_new_from_string(string name)
+ {
+ godot_node_path ret;
+ using godot_string src = Marshaling.mono_string_to_godot(name);
+ godotsharp_node_path_new_from_string(&ret, &src);
+ return ret;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs
new file mode 100644
index 0000000000..2814f9d506
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Godot.NativeInterop
+{
+ internal ref struct VariantSpanDisposer
+ {
+ private readonly Span<godot_variant> _variantSpan;
+
+ // IMPORTANT: The span element must be default initialized.
+ // Make sure call Clear() on the span if it was created with stackalloc.
+ public VariantSpanDisposer(Span<godot_variant> variantSpan)
+ {
+ _variantSpan = variantSpan;
+ }
+
+ public void Dispose()
+ {
+ for (int i = 0; i < _variantSpan.Length; i++)
+ _variantSpan[i].Dispose();
+ }
+ }
+
+ internal static class VariantSpanExtensions
+ {
+ // Used to make sure we always initialize the span values to the default,
+ // as we need that in order to safely dispose all elements after.
+ public static Span<godot_variant> Cleared(this Span<godot_variant> span)
+ {
+ span.Clear();
+ return span;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
new file mode 100644
index 0000000000..67f9e23893
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Runtime.CompilerServices;
+
+// ReSharper disable InconsistentNaming
+
+namespace Godot.NativeInterop
+{
+ internal static class VariantUtils
+ {
+ public static godot_variant CreateFromRID(RID from)
+ => new() {_type = Variant.Type.Rid, _data = {_m_rid = from}};
+
+ public static godot_variant CreateFromBool(bool from)
+ => new() {_type = Variant.Type.Bool, _data = {_bool = from}};
+
+ public static godot_variant CreateFromInt(long from)
+ => new() {_type = Variant.Type.Int, _data = {_int = from}};
+
+ public static godot_variant CreateFromInt(ulong from)
+ => new() {_type = Variant.Type.Int, _data = {_int = (long)from}};
+
+ public static godot_variant CreateFromFloat(double from)
+ => new() {_type = Variant.Type.Float, _data = {_float = from}};
+
+ public static godot_variant CreateFromVector2(Vector2 from)
+ => new() {_type = Variant.Type.Vector2, _data = {_m_vector2 = from}};
+
+ public static godot_variant CreateFromVector2i(Vector2i from)
+ => new() {_type = Variant.Type.Vector2i, _data = {_m_vector2i = from}};
+
+ public static godot_variant CreateFromVector3(Vector3 from)
+ => new() {_type = Variant.Type.Vector3, _data = {_m_vector3 = from}};
+
+ public static godot_variant CreateFromVector3i(Vector3i from)
+ => new() {_type = Variant.Type.Vector3i, _data = {_m_vector3i = from}};
+
+ public static godot_variant CreateFromRect2(Rect2 from)
+ => new() {_type = Variant.Type.Rect2, _data = {_m_rect2 = from}};
+
+ public static godot_variant CreateFromRect2i(Rect2i from)
+ => new() {_type = Variant.Type.Rect2i, _data = {_m_rect2i = from}};
+
+ public static godot_variant CreateFromQuaternion(Quaternion from)
+ => new() {_type = Variant.Type.Quaternion, _data = {_m_quaternion = from}};
+
+ public static godot_variant CreateFromColor(Color from)
+ => new() {_type = Variant.Type.Color, _data = {_m_color = from}};
+
+ public static godot_variant CreateFromPlane(Plane from)
+ => new() {_type = Variant.Type.Plane, _data = {_m_plane = from}};
+
+ public static unsafe godot_variant CreateFromTransform2D(Transform2D from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_transform2d(&ret, &from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromVector4(Vector4 from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_vector4(&ret, &from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromVector4i(Vector4i from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_vector4i(&ret, &from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromBasis(Basis from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_basis(&ret, &from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromTransform3D(Transform3D from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_transform3d(&ret, &from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromProjection(Projection from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_projection(&ret, &from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromAABB(AABB from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_aabb(&ret, &from);
+ return ret;
+ }
+
+ // Explicit name to make it very clear
+ public static godot_variant CreateFromCallableTakingOwnershipOfDisposableValue(godot_callable from)
+ => new() {_type = Variant.Type.Callable, _data = {_m_callable = from}};
+
+ // Explicit name to make it very clear
+ public static godot_variant CreateFromSignalTakingOwnershipOfDisposableValue(godot_signal from)
+ => new() {_type = Variant.Type.Signal, _data = {_m_signal = from}};
+
+ // Explicit name to make it very clear
+ public static godot_variant CreateFromStringTakingOwnershipOfDisposableValue(godot_string from)
+ => new() {_type = Variant.Type.String, _data = {_m_string = from}};
+
+ public static unsafe godot_variant CreateFromPackedByteArray(godot_packed_byte_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_byte_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedInt32Array(godot_packed_int32_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_int32_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedInt64Array(godot_packed_int64_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_int64_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedFloat32Array(godot_packed_float32_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_float32_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedFloat64Array(godot_packed_float64_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_float64_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedStringArray(godot_packed_string_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_string_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedVector2Array(godot_packed_vector2_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_vector2_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedVector3Array(godot_packed_vector3_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_vector3_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromPackedColorArray(godot_packed_color_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_packed_color_array(&ret, from);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromArray(godot_array* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_array(&ret, from);
+ return ret;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe godot_variant CreateFromArray(godot_array from)
+ => CreateFromArray(&from);
+
+ public static unsafe godot_variant CreateFromDictionary(godot_dictionary* from)
+ {
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_dictionary(&ret, from);
+ return ret;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe godot_variant CreateFromDictionary(godot_dictionary from)
+ => CreateFromDictionary(&from);
+
+ public static unsafe godot_variant CreateFromStringName(ref godot_string_name arg1)
+ {
+ godot_variant ret;
+ godot_string_name src = arg1;
+ NativeFuncs.godotsharp_variant_new_string_name(&ret, &src);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromNodePath(ref godot_node_path arg1)
+ {
+ godot_variant ret;
+ godot_node_path src = arg1;
+ NativeFuncs.godotsharp_variant_new_node_path(&ret, &src);
+ return ret;
+ }
+
+ public static unsafe godot_variant CreateFromGodotObject(IntPtr from)
+ {
+ if (from == IntPtr.Zero)
+ return new godot_variant();
+ godot_variant ret;
+ NativeFuncs.godotsharp_variant_new_object(&ret, from);
+ return ret;
+ }
+
+ // We avoid the internal call if the stored type is the same we want.
+
+ public static unsafe bool ConvertToBool(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Bool ? (*p_var)._data._bool : NativeFuncs.godotsharp_variant_as_bool(p_var);
+
+ public static unsafe char ConvertToChar(godot_variant* p_var)
+ => (char)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe sbyte ConvertToInt8(godot_variant* p_var)
+ => (sbyte)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe Int16 ConvertToInt16(godot_variant* p_var)
+ => (Int16)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe Int32 ConvertToInt32(godot_variant* p_var)
+ => (Int32)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe Int64 ConvertToInt64(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var);
+
+ public static unsafe byte ConvertToUInt8(godot_variant* p_var)
+ => (byte)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe UInt16 ConvertToUInt16(godot_variant* p_var)
+ => (UInt16)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe UInt32 ConvertToUInt32(godot_variant* p_var)
+ => (UInt32)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe UInt64 ConvertToUInt64(godot_variant* p_var)
+ => (UInt64)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
+
+ public static unsafe float ConvertToFloat32(godot_variant* p_var)
+ => (float)((*p_var)._type == Variant.Type.Float ? (*p_var)._data._float : NativeFuncs.godotsharp_variant_as_float(p_var));
+
+ public static unsafe double ConvertToFloat64(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Float ? (*p_var)._data._float : NativeFuncs.godotsharp_variant_as_float(p_var);
+
+ public static unsafe Vector2 ConvertToVector2(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Vector2 ? (*p_var)._data._m_vector2 : NativeFuncs.godotsharp_variant_as_vector2(p_var);
+
+ public static unsafe Vector2i ConvertToVector2i(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Vector2i ? (*p_var)._data._m_vector2i : NativeFuncs.godotsharp_variant_as_vector2i(p_var);
+
+ public static unsafe Rect2 ConvertToRect2(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Rect2 ? (*p_var)._data._m_rect2 : NativeFuncs.godotsharp_variant_as_rect2(p_var);
+
+ public static unsafe Rect2i ConvertToRect2i(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Rect2i ? (*p_var)._data._m_rect2i : NativeFuncs.godotsharp_variant_as_rect2i(p_var);
+
+ public static unsafe Transform2D ConvertToTransform2D(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Transform2d ? *(*p_var)._data._transform2d : NativeFuncs.godotsharp_variant_as_transform2d(p_var);
+
+ public static unsafe Vector3 ConvertToVector3(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Vector3 ? (*p_var)._data._m_vector3 : NativeFuncs.godotsharp_variant_as_vector3(p_var);
+
+ public static unsafe Vector3i ConvertToVector3i(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Vector3i ? (*p_var)._data._m_vector3i : NativeFuncs.godotsharp_variant_as_vector3i(p_var);
+
+ public static unsafe Vector4 ConvertToVector4(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Vector4 ? *(*p_var)._data._vector4 : NativeFuncs.godotsharp_variant_as_vector4(p_var);
+
+ public static unsafe Vector4i ConvertToVector4i(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Vector4i ? *(*p_var)._data._vector4i : NativeFuncs.godotsharp_variant_as_vector4i(p_var);
+
+ public static unsafe Basis ConvertToBasis(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Basis ? *(*p_var)._data._basis : NativeFuncs.godotsharp_variant_as_basis(p_var);
+
+ public static unsafe Quaternion ConvertToQuaternion(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Quaternion ? (*p_var)._data._m_quaternion : NativeFuncs.godotsharp_variant_as_quaternion(p_var);
+
+ public static unsafe Transform3D ConvertToTransform3D(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Transform3d ? *(*p_var)._data._transform3d : NativeFuncs.godotsharp_variant_as_transform3d(p_var);
+
+ public static unsafe Projection ConvertToProjection(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Projection ? *(*p_var)._data._projection : NativeFuncs.godotsharp_variant_as_projection(p_var);
+
+ public static unsafe AABB ConvertToAABB(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Aabb ? *(*p_var)._data._aabb : NativeFuncs.godotsharp_variant_as_aabb(p_var);
+
+ public static unsafe Color ConvertToColor(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Color ? (*p_var)._data._m_color : NativeFuncs.godotsharp_variant_as_color(p_var);
+
+ public static unsafe Plane ConvertToPlane(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Plane ? (*p_var)._data._m_plane : NativeFuncs.godotsharp_variant_as_plane(p_var);
+
+ public static unsafe IntPtr ConvertToGodotObject(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Object ? (*p_var)._data._m_obj_data.obj : IntPtr.Zero;
+
+ public static unsafe RID ConvertToRID(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Rid ? (*p_var)._data._m_rid : NativeFuncs.godotsharp_variant_as_rid(p_var);
+
+ public static unsafe godot_string_name ConvertToStringName(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.StringName ?
+ NativeFuncs.godotsharp_string_name_new_copy(&(*p_var)._data._m_string_name) :
+ NativeFuncs.godotsharp_variant_as_string_name(p_var);
+
+ public static unsafe godot_node_path ConvertToNodePath(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.NodePath ?
+ NativeFuncs.godotsharp_node_path_new_copy(&(*p_var)._data._m_node_path) :
+ NativeFuncs.godotsharp_variant_as_node_path(p_var);
+
+ public static unsafe godot_array ConvertToArray(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Array ?
+ NativeFuncs.godotsharp_array_new_copy(&(*p_var)._data._m_array) :
+ NativeFuncs.godotsharp_variant_as_array(p_var);
+
+ public static unsafe godot_dictionary ConvertToDictionary(godot_variant* p_var)
+ => (*p_var)._type == Variant.Type.Dictionary ?
+ NativeFuncs.godotsharp_dictionary_new_copy(&(*p_var)._data._m_dictionary) :
+ NativeFuncs.godotsharp_variant_as_dictionary(p_var);
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
index 9ae01016cb..90e51e8a1a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.CompilerServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -39,22 +40,9 @@ namespace Godot
/// new NodePath("/root/MyAutoload"); // If you have an autoloaded node or scene.
/// </code>
/// </example>
- public sealed partial class NodePath : IDisposable
+ public sealed class NodePath : IDisposable
{
- private bool _disposed = false;
-
- private IntPtr ptr;
-
- internal static IntPtr GetPtr(NodePath instance)
- {
- if (instance == null)
- throw new NullReferenceException($"The instance of type {nameof(NodePath)} is null.");
-
- if (instance._disposed)
- throw new ObjectDisposedException(instance.GetType().FullName);
-
- return instance.ptr;
- }
+ internal godot_node_path NativeValue;
~NodePath()
{
@@ -70,29 +58,27 @@ namespace Godot
GC.SuppressFinalize(this);
}
- private void Dispose(bool disposing)
+ public void Dispose(bool disposing)
{
- if (_disposed)
- return;
-
- if (ptr != IntPtr.Zero)
- {
- godot_icall_NodePath_Dtor(ptr);
- ptr = IntPtr.Zero;
- }
-
- _disposed = true;
+ // Always dispose `NativeValue` even if disposing is true
+ NativeValue.Dispose();
}
- internal NodePath(IntPtr ptr)
+ private NodePath(godot_node_path nativeValueToOwn)
{
- this.ptr = ptr;
+ NativeValue = nativeValueToOwn;
}
+ // Explicit name to make it very clear
+ internal static NodePath CreateTakingOwnershipOfDisposableValue(godot_node_path nativeValueToOwn)
+ => new NodePath(nativeValueToOwn);
+
/// <summary>
/// Constructs an empty <see cref="NodePath"/>.
/// </summary>
- public NodePath() : this(string.Empty) { }
+ public NodePath()
+ {
+ }
/// <summary>
/// Constructs a <see cref="NodePath"/> from a string <paramref name="path"/>,
@@ -125,7 +111,8 @@ namespace Godot
/// <param name="path">A string that represents a path in a scene tree.</param>
public NodePath(string path)
{
- ptr = godot_icall_NodePath_Ctor(path);
+ if (!string.IsNullOrEmpty(path))
+ NativeValue = NativeFuncs.godotsharp_node_path_new_from_string(path);
}
/// <summary>
@@ -144,9 +131,16 @@ namespace Godot
/// Converts this <see cref="NodePath"/> to a string.
/// </summary>
/// <returns>A string representation of this <see cref="NodePath"/>.</returns>
- public override string ToString()
+ public override unsafe string ToString()
{
- return godot_icall_NodePath_operator_String(GetPtr(this));
+ if (IsEmpty)
+ return string.Empty;
+
+ godot_string dest;
+ godot_node_path src = NativeValue;
+ NativeFuncs.godotsharp_node_path_as_string(&dest, &src);
+ using (dest)
+ return Marshaling.mono_string_from_godot(&dest);
}
/// <summary>
@@ -166,7 +160,9 @@ namespace Godot
/// <returns>The <see cref="NodePath"/> as a pure property path.</returns>
public NodePath GetAsPropertyPath()
{
- return new NodePath(godot_icall_NodePath_get_as_property_path(GetPtr(this)));
+ godot_node_path propertyPath = default;
+ godot_icall_NodePath_get_as_property_path(ref NativeValue, ref propertyPath);
+ return CreateTakingOwnershipOfDisposableValue(propertyPath);
}
/// <summary>
@@ -181,7 +177,7 @@ namespace Godot
/// <returns>The names concatenated with <c>/</c>.</returns>
public string GetConcatenatedNames()
{
- return godot_icall_NodePath_get_concatenated_names(GetPtr(this));
+ return godot_icall_NodePath_get_concatenated_names(ref NativeValue);
}
/// <summary>
@@ -195,9 +191,9 @@ namespace Godot
/// </code>
/// </example>
/// <returns>The subnames concatenated with <c>:</c>.</returns>
- public string GetConcatenatedSubnames()
+ public string GetConcatenatedSubNames()
{
- return godot_icall_NodePath_get_concatenated_subnames(GetPtr(this));
+ return godot_icall_NodePath_get_concatenated_subnames(ref NativeValue);
}
/// <summary>
@@ -215,28 +211,28 @@ namespace Godot
/// <returns>The name at the given index <paramref name="idx"/>.</returns>
public string GetName(int idx)
{
- return godot_icall_NodePath_get_name(GetPtr(this), idx);
+ return godot_icall_NodePath_get_name(ref NativeValue, idx);
}
/// <summary>
/// Gets the number of node names which make up the path.
- /// Subnames (see <see cref="GetSubnameCount"/>) are not included.
+ /// Subnames (see <see cref="GetSubNameCount"/>) are not included.
/// For example, <c>"Path2D/PathFollow2D/Sprite2D"</c> has 3 names.
/// </summary>
/// <returns>The number of node names which make up the path.</returns>
public int GetNameCount()
{
- return godot_icall_NodePath_get_name_count(GetPtr(this));
+ return godot_icall_NodePath_get_name_count(ref NativeValue);
}
/// <summary>
- /// Gets the resource or property name indicated by <paramref name="idx"/> (0 to <see cref="GetSubnameCount"/>).
+ /// Gets the resource or property name indicated by <paramref name="idx"/> (0 to <see cref="GetSubNameCount"/>).
/// </summary>
/// <param name="idx">The subname index.</param>
/// <returns>The subname at the given index <paramref name="idx"/>.</returns>
- public string GetSubname(int idx)
+ public string GetSubName(int idx)
{
- return godot_icall_NodePath_get_subname(GetPtr(this), idx);
+ return godot_icall_NodePath_get_subname(ref NativeValue, idx);
}
/// <summary>
@@ -245,9 +241,9 @@ namespace Godot
/// For example, <c>"Path2D/PathFollow2D/Sprite2D:texture:load_path"</c> has 2 subnames.
/// </summary>
/// <returns>The number of subnames in the path.</returns>
- public int GetSubnameCount()
+ public int GetSubNameCount()
{
- return godot_icall_NodePath_get_subname_count(GetPtr(this));
+ return godot_icall_NodePath_get_subname_count(ref NativeValue);
}
/// <summary>
@@ -259,52 +255,37 @@ namespace Godot
/// <returns>If the <see cref="NodePath"/> is an absolute path.</returns>
public bool IsAbsolute()
{
- return godot_icall_NodePath_is_absolute(GetPtr(this));
+ return godot_icall_NodePath_is_absolute(ref NativeValue);
}
/// <summary>
/// Returns <see langword="true"/> if the node path is empty.
/// </summary>
/// <returns>If the <see cref="NodePath"/> is empty.</returns>
- public bool IsEmpty()
- {
- return godot_icall_NodePath_is_empty(GetPtr(this));
- }
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern IntPtr godot_icall_NodePath_Ctor(string path);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void godot_icall_NodePath_Dtor(IntPtr ptr);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern string godot_icall_NodePath_operator_String(IntPtr ptr);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr);
+ public bool IsEmpty => godot_node_path.IsEmpty(in NativeValue);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern string godot_icall_NodePath_get_concatenated_names(IntPtr ptr);
+ private static extern void godot_icall_NodePath_get_as_property_path(ref godot_node_path ptr, ref godot_node_path dest);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr);
+ private static extern string godot_icall_NodePath_get_concatenated_names(ref godot_node_path ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern string godot_icall_NodePath_get_name(IntPtr ptr, int arg1);
+ private static extern string godot_icall_NodePath_get_concatenated_subnames(ref godot_node_path ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern int godot_icall_NodePath_get_name_count(IntPtr ptr);
+ private static extern string godot_icall_NodePath_get_name(ref godot_node_path ptr, int arg1);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern string godot_icall_NodePath_get_subname(IntPtr ptr, int arg1);
+ private static extern int godot_icall_NodePath_get_name_count(ref godot_node_path ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern int godot_icall_NodePath_get_subname_count(IntPtr ptr);
+ private static extern string godot_icall_NodePath_get_subname(ref godot_node_path ptr, int arg1);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool godot_icall_NodePath_is_absolute(IntPtr ptr);
+ private static extern int godot_icall_NodePath_get_subname_count(ref godot_node_path ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool godot_icall_NodePath_is_empty(IntPtr ptr);
+ private static extern bool godot_icall_NodePath_is_absolute(ref godot_node_path ptr);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
index 746612477d..80d63581c1 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
@@ -7,38 +7,44 @@ namespace Godot
{
private bool _disposed = false;
- private static StringName nativeName = "Object";
-
- internal IntPtr ptr;
- internal bool memoryOwn;
+ internal IntPtr NativePtr;
+ internal bool MemoryOwn;
/// <summary>
/// Constructs a new <see cref="Object"/>.
/// </summary>
public Object() : this(false)
{
- if (ptr == IntPtr.Zero)
- ptr = godot_icall_Object_Ctor(this);
+ if (NativePtr == IntPtr.Zero)
+ {
+#if NET
+ unsafe
+ {
+ ptr = NativeCtor();
+ }
+#else
+ NativePtr = _gd__invoke_class_constructor(NativeCtor);
+#endif
+ NativeInterop.InteropUtils.TieManagedToUnmanaged(this, NativePtr);
+ }
+
_InitializeGodotScriptInstanceInternals();
}
internal void _InitializeGodotScriptInstanceInternals()
{
- godot_icall_Object_ConnectEventSignals(ptr);
+ godot_icall_Object_ConnectEventSignals(NativePtr);
}
internal Object(bool memoryOwn)
{
- this.memoryOwn = memoryOwn;
+ this.MemoryOwn = memoryOwn;
}
/// <summary>
/// The pointer to the native instance of this <see cref="Object"/>.
/// </summary>
- public IntPtr NativeInstance
- {
- get { return ptr; }
- }
+ public IntPtr NativeInstance => NativePtr;
internal static IntPtr GetPtr(Object instance)
{
@@ -48,7 +54,7 @@ namespace Godot
if (instance._disposed)
throw new ObjectDisposedException(instance.GetType().FullName);
- return instance.ptr;
+ return instance.NativePtr;
}
~Object()
@@ -73,19 +79,19 @@ namespace Godot
if (_disposed)
return;
- if (ptr != IntPtr.Zero)
+ if (NativePtr != IntPtr.Zero)
{
- if (memoryOwn)
+ if (MemoryOwn)
{
- memoryOwn = false;
- godot_icall_RefCounted_Disposed(this, ptr, !disposing);
+ MemoryOwn = false;
+ godot_icall_RefCounted_Disposed(this, NativePtr, !disposing);
}
else
{
- godot_icall_Object_Disposed(this, ptr);
+ godot_icall_Object_Disposed(this, NativePtr);
}
- ptr = IntPtr.Zero;
+ this.NativePtr = IntPtr.Zero;
}
_disposed = true;
@@ -137,13 +143,49 @@ namespace Godot
/// </summary>
public dynamic DynamicObject => new DynamicGodotObject(this);
- internal static IntPtr __ClassDB_get_method(StringName type, string method)
+ internal static unsafe IntPtr ClassDB_get_method(StringName type, string method)
+ {
+ IntPtr methodBind;
+ fixed (char* methodChars = method)
+ {
+ methodBind = NativeInterop.NativeFuncs
+ .godotsharp_method_bind_get_method(ref type.NativeValue, methodChars);
+ }
+
+ if (methodBind == IntPtr.Zero)
+ throw new NativeMethodBindNotFoundException(type + "." + method);
+
+ return methodBind;
+ }
+
+#if NET
+ internal static unsafe delegate* unmanaged<IntPtr> _gd__ClassDB_get_constructor(StringName type)
+ {
+ // for some reason the '??' operator doesn't support 'delegate*'
+ var nativeConstructor = NativeInterop.NativeFuncs
+ .godotsharp_get_class_constructor(ref type.NativeValue);
+
+ if (nativeConstructor == null)
+ throw new NativeConstructorNotFoundException(type);
+
+ return nativeConstructor;
+ }
+#else
+ internal static IntPtr ClassDB_get_constructor(StringName type)
{
- return godot_icall_Object_ClassDB_get_method(StringName.GetPtr(type), method);
+ // for some reason the '??' operator doesn't support 'delegate*'
+ var nativeConstructor = NativeInterop.NativeFuncs
+ .godotsharp_get_class_constructor(ref type.NativeValue);
+
+ if (nativeConstructor == IntPtr.Zero)
+ throw new NativeConstructorNotFoundException(type);
+
+ return nativeConstructor;
}
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Object_Ctor(Object obj);
+ internal static IntPtr _gd__invoke_class_constructor(IntPtr ctorFuncPtr)
+ => NativeInterop.NativeFuncs.godotsharp_invoke_class_constructor(ctorFuncPtr);
+#endif
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr);
@@ -156,9 +198,5 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern string godot_icall_Object_ToString(IntPtr ptr);
-
- // Used by the generated API
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_Object_ClassDB_get_method(IntPtr type, string method);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.exceptions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.exceptions.cs
new file mode 100644
index 0000000000..eb2811c73d
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.exceptions.cs
@@ -0,0 +1,135 @@
+using System;
+
+#nullable enable
+
+namespace Godot
+{
+ public partial class Object
+ {
+ public class NativeMemberNotFoundException : Exception
+ {
+ public NativeMemberNotFoundException()
+ {
+ }
+
+ public NativeMemberNotFoundException(string? message) : base(message)
+ {
+ }
+
+ public NativeMemberNotFoundException(string? message, Exception? innerException)
+ : base(message, innerException)
+ {
+ }
+ }
+
+ public class NativeConstructorNotFoundException : NativeMemberNotFoundException
+ {
+ private readonly string? _nativeClassName;
+
+ // ReSharper disable once InconsistentNaming
+ private const string Arg_NativeConstructorNotFoundException = "Unable to find the native constructor.";
+
+ public NativeConstructorNotFoundException()
+ : base(Arg_NativeConstructorNotFoundException)
+ {
+ }
+
+ public NativeConstructorNotFoundException(string? nativeClassName)
+ : this(Arg_NativeConstructorNotFoundException, nativeClassName)
+ {
+ }
+
+ public NativeConstructorNotFoundException(string? message, Exception? innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public NativeConstructorNotFoundException(string? message, string? nativeClassName)
+ : base(message)
+ {
+ _nativeClassName = nativeClassName;
+ }
+
+ public NativeConstructorNotFoundException(string? message, string? nativeClassName, Exception? innerException)
+ : base(message, innerException)
+ {
+ _nativeClassName = nativeClassName;
+ }
+
+ public override string Message
+ {
+ get
+ {
+ string s = base.Message;
+
+ if (string.IsNullOrEmpty(s))
+ {
+ s = Arg_NativeConstructorNotFoundException;
+ }
+
+ if (!string.IsNullOrEmpty(_nativeClassName))
+ {
+ s += " " + string.Format("(Class '{0}')", _nativeClassName);
+ }
+
+ return s;
+ }
+ }
+ }
+
+ public class NativeMethodBindNotFoundException : NativeMemberNotFoundException
+ {
+ private readonly string? _nativeMethodName;
+
+ // ReSharper disable once InconsistentNaming
+ private const string Arg_NativeMethodBindNotFoundException = "Unable to find the native method bind.";
+
+ public NativeMethodBindNotFoundException()
+ : base(Arg_NativeMethodBindNotFoundException)
+ {
+ }
+
+ public NativeMethodBindNotFoundException(string? nativeMethodName)
+ : this(Arg_NativeMethodBindNotFoundException, nativeMethodName)
+ {
+ }
+
+ public NativeMethodBindNotFoundException(string? message, Exception? innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public NativeMethodBindNotFoundException(string? message, string? nativeMethodName)
+ : base(message)
+ {
+ _nativeMethodName = nativeMethodName;
+ }
+
+ public NativeMethodBindNotFoundException(string? message, string? nativeMethodName, Exception? innerException)
+ : base(message, innerException)
+ {
+ _nativeMethodName = nativeMethodName;
+ }
+
+ public override string Message
+ {
+ get
+ {
+ string s = base.Message;
+
+ if (string.IsNullOrEmpty(s))
+ {
+ s = Arg_NativeMethodBindNotFoundException;
+ }
+
+ if (!string.IsNullOrEmpty(_nativeMethodName))
+ {
+ s += " " + string.Format("(Method '{0}')", _nativeMethodName);
+ }
+
+ return s;
+ }
+ }
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
index 1588869ec0..a31fef8360 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
@@ -1,5 +1,7 @@
using System;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -9,99 +11,32 @@ namespace Godot
/// resource by themselves. They are used by and with the low-level Server
/// classes such as <see cref="RenderingServer"/>.
/// </summary>
- public sealed partial class RID : IDisposable
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RID
{
- private bool _disposed = false;
+ private ulong _id; // Default is 0
- internal IntPtr ptr;
-
- internal static IntPtr GetPtr(RID instance)
- {
- if (instance == null)
- throw new NullReferenceException($"The instance of type {nameof(RID)} is null.");
-
- if (instance._disposed)
- throw new ObjectDisposedException(instance.GetType().FullName);
-
- return instance.ptr;
- }
-
- ~RID()
- {
- Dispose(false);
- }
-
- /// <summary>
- /// Disposes of this <see cref="RID"/>.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- private void Dispose(bool disposing)
- {
- if (_disposed)
- return;
-
- if (ptr != IntPtr.Zero)
- {
- godot_icall_RID_Dtor(ptr);
- ptr = IntPtr.Zero;
- }
-
- _disposed = true;
- }
-
- internal RID(IntPtr ptr)
+ internal RID(ulong id)
{
- this.ptr = ptr;
- }
-
- /// <summary>
- /// The pointer to the native instance of this <see cref="RID"/>.
- /// </summary>
- public IntPtr NativeInstance
- {
- get { return ptr; }
- }
-
- internal RID()
- {
- this.ptr = IntPtr.Zero;
+ _id = id;
}
/// <summary>
/// Constructs a new <see cref="RID"/> for the given <see cref="Object"/> <paramref name="from"/>.
/// </summary>
public RID(Object from)
- {
- this.ptr = godot_icall_RID_Ctor(Object.GetPtr(from));
- }
+ => _id = from is Resource res ? res.GetRid()._id : default;
/// <summary>
/// Returns the ID of the referenced resource.
/// </summary>
/// <returns>The ID of the referenced resource.</returns>
- public int GetId()
- {
- return godot_icall_RID_get_id(GetPtr(this));
- }
+ public ulong Id => _id;
/// <summary>
/// Converts this <see cref="RID"/> to a string.
/// </summary>
/// <returns>A string representation of this RID.</returns>
- public override string ToString() => "[RID]";
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern IntPtr godot_icall_RID_Ctor(IntPtr from);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void godot_icall_RID_Dtor(IntPtr ptr);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int godot_icall_RID_get_id(IntPtr ptr);
+ public override string ToString() => $"RID({Id})";
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
index 2ba0493002..e485207fb4 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.CompilerServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -11,34 +12,22 @@ namespace Godot
public SignalAwaiter(Object source, StringName signal, Object target)
{
- godot_icall_SignalAwaiter_connect(Object.GetPtr(source), StringName.GetPtr(signal), Object.GetPtr(target), this);
+ godot_icall_SignalAwaiter_connect(Object.GetPtr(source), ref signal.NativeValue, Object.GetPtr(target), this);
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern Error godot_icall_SignalAwaiter_connect(IntPtr source, IntPtr signal, IntPtr target, SignalAwaiter awaiter);
+ internal static extern Error godot_icall_SignalAwaiter_connect(IntPtr source, ref godot_string_name signal, IntPtr target, SignalAwaiter awaiter);
- public bool IsCompleted
- {
- get
- {
- return _completed;
- }
- }
+ public bool IsCompleted => _completed;
public void OnCompleted(Action action)
{
this._action = action;
}
- public object[] GetResult()
- {
- return _result;
- }
+ public object[] GetResult() => _result;
- public IAwaiter<object[]> GetAwaiter()
- {
- return this;
- }
+ public IAwaiter<object[]> GetAwaiter() => this;
internal void SignalCallback(object[] args)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index a1f058ffe5..058c5447e2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -214,7 +214,7 @@ namespace Godot
/// <returns>The escaped string.</returns>
public static string CEscape(this string instance)
{
- var sb = new StringBuilder(string.Copy(instance));
+ var sb = new StringBuilder(instance);
sb.Replace("\\", "\\\\");
sb.Replace("\a", "\\a");
@@ -239,7 +239,7 @@ namespace Godot
/// <returns>The unescaped string.</returns>
public static string CUnescape(this string instance)
{
- var sb = new StringBuilder(string.Copy(instance));
+ var sb = new StringBuilder(instance);
sb.Replace("\\a", "\a");
sb.Replace("\\b", "\b");
@@ -926,7 +926,7 @@ namespace Godot
/// <returns>The escaped string.</returns>
public static string JSONEscape(this string instance)
{
- var sb = new StringBuilder(string.Copy(instance));
+ var sb = new StringBuilder(instance);
sb.Replace("\\", "\\\\");
sb.Replace("\b", "\\b");
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
index b1d504410b..40d282eab4 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.CompilerServices;
+using Godot.NativeInterop;
namespace Godot
{
@@ -10,20 +11,9 @@ namespace Godot
/// Comparing them is much faster than with regular strings, because only the pointers are compared,
/// not the whole strings.
/// </summary>
- public sealed partial class StringName : IDisposable
+ public sealed class StringName : IDisposable
{
- private IntPtr ptr;
-
- internal static IntPtr GetPtr(StringName instance)
- {
- if (instance == null)
- throw new NullReferenceException($"The instance of type {nameof(StringName)} is null.");
-
- if (instance.ptr == IntPtr.Zero)
- throw new ObjectDisposedException(instance.GetType().FullName);
-
- return instance.ptr;
- }
+ internal godot_string_name NativeValue;
~StringName()
{
@@ -39,35 +29,36 @@ namespace Godot
GC.SuppressFinalize(this);
}
- private void Dispose(bool disposing)
+ public void Dispose(bool disposing)
{
- if (ptr != IntPtr.Zero)
- {
- godot_icall_StringName_Dtor(ptr);
- ptr = IntPtr.Zero;
- }
+ // Always dispose `NativeValue` even if disposing is true
+ NativeValue.Dispose();
}
- internal StringName(IntPtr ptr)
+ private StringName(godot_string_name nativeValueToOwn)
{
- this.ptr = ptr;
+ NativeValue = nativeValueToOwn;
}
+ // Explicit name to make it very clear
+ internal static StringName CreateTakingOwnershipOfDisposableValue(godot_string_name nativeValueToOwn)
+ => new StringName(nativeValueToOwn);
+
/// <summary>
/// Constructs an empty <see cref="StringName"/>.
/// </summary>
public StringName()
{
- ptr = IntPtr.Zero;
}
/// <summary>
/// Constructs a <see cref="StringName"/> from the given <paramref name="path"/> string.
/// </summary>
/// <param name="path">String to construct the <see cref="StringName"/> from.</param>
- public StringName(string path)
+ public StringName(string name)
{
- ptr = path == null ? IntPtr.Zero : godot_icall_StringName_Ctor(path);
+ if (!string.IsNullOrEmpty(name))
+ NativeValue = NativeFuncs.godotsharp_string_name_new_from_string(name);
}
/// <summary>
@@ -86,30 +77,22 @@ namespace Godot
/// Converts this <see cref="StringName"/> to a string.
/// </summary>
/// <returns>A string representation of this <see cref="StringName"/>.</returns>
- public override string ToString()
+ public override unsafe string ToString()
{
- return ptr == IntPtr.Zero ? string.Empty : godot_icall_StringName_operator_String(GetPtr(this));
+ if (IsEmpty)
+ return string.Empty;
+
+ godot_string dest;
+ godot_string_name src = NativeValue;
+ NativeFuncs.godotsharp_string_name_as_string(&dest, &src);
+ using (dest)
+ return Marshaling.mono_string_from_godot(&dest);
}
/// <summary>
/// Check whether this <see cref="StringName"/> is empty.
/// </summary>
/// <returns>If the <see cref="StringName"/> is empty.</returns>
- public bool IsEmpty()
- {
- return ptr == IntPtr.Zero || godot_icall_StringName_is_empty(GetPtr(this));
- }
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern IntPtr godot_icall_StringName_Ctor(string path);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void godot_icall_StringName_Dtor(IntPtr ptr);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern string godot_icall_StringName_operator_String(IntPtr ptr);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool godot_icall_StringName_is_empty(IntPtr ptr);
+ public bool IsEmpty => godot_string_name.IsEmpty(in NativeValue);
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 4f55ce47e8..9683d8e812 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -7,11 +7,20 @@
<TargetFramework>netstandard2.1</TargetFramework>
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
<EnableDefaultItems>false</EnableDefaultItems>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <LangVersion>9</LangVersion>
+
+ <!-- Disabled temporarily as it pollutes the warnings, but we need to document public APIs. -->
+ <NoWarn>CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
</PropertyGroup>
<ItemGroup>
+ <PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
+ <!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
+ </ItemGroup>
+ <ItemGroup>
<Compile Include="Core\AABB.cs" />
<Compile Include="Core\Array.cs" />
<Compile Include="Core\Attributes\AssemblyHasScriptsAttribute.cs" />
@@ -47,14 +56,22 @@
<Compile Include="Core\MarshalUtils.cs" />
<Compile Include="Core\Mathf.cs" />
<Compile Include="Core\MathfEx.cs" />
+ <Compile Include="Core\NativeInterop\InteropUtils.cs" />
+ <Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
+ <Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
+ <Compile Include="Core\NativeInterop\VariantUtils.cs" />
<Compile Include="Core\NodePath.cs" />
<Compile Include="Core\Object.base.cs" />
+ <Compile Include="Core\Object.exceptions.cs" />
<Compile Include="Core\Plane.cs" />
<Compile Include="Core\Projection.cs" />
<Compile Include="Core\Quaternion.cs" />
<Compile Include="Core\Rect2.cs" />
<Compile Include="Core\Rect2i.cs" />
<Compile Include="Core\RID.cs" />
+ <Compile Include="Core\NativeInterop\NativeFuncs.cs" />
+ <Compile Include="Core\NativeInterop\InteropStructs.cs" />
+ <Compile Include="Core\NativeInterop\Marshaling.cs" />
<Compile Include="Core\SignalInfo.cs" />
<Compile Include="Core\SignalAwaiter.cs" />
<Compile Include="Core\StringExtensions.cs" />
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj.DotSettings b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj.DotSettings
new file mode 100644
index 0000000000..1add6cc77e
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj.DotSettings
@@ -0,0 +1,5 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+ <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated_005Cgodotobjects/@EntryIndexedValue">True</s:Boolean>
+</wpf:ResourceDictionary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
index a8c4ba96b5..1082c74448 100644
--- a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
@@ -7,6 +7,8 @@
<TargetFramework>netstandard2.1</TargetFramework>
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
<EnableDefaultItems>false</EnableDefaultItems>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <LangVersion>9</LangVersion>
</PropertyGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
diff --git a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj.DotSettings b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj.DotSettings
new file mode 100644
index 0000000000..c7ff6fd3ee
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj.DotSettings
@@ -0,0 +1,4 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+ <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated_005Cgodotobjects/@EntryIndexedValue">True</s:Boolean>
+</wpf:ResourceDictionary>
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 7b9dbc87cf..05a8ef20f9 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef MONO_GLUE_ENABLED
-
#include "core/object/class_db.h"
#include "core/object/ref_counted.h"
#include "core/string/string_name.h"
@@ -43,12 +41,6 @@
#include "../signal_awaiter_utils.h"
#include "arguments_vector.h"
-Object *godot_icall_Object_Ctor(MonoObject *p_obj) {
- Object *instance = memnew(Object);
- GDMonoInternals::tie_managed_to_unmanaged(p_obj, instance);
- return instance;
-}
-
void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
#ifdef DEBUG_ENABLED
CRASH_COND(p_ptr == nullptr);
@@ -133,12 +125,6 @@ void godot_icall_Object_ConnectEventSignals(Object *p_ptr) {
}
}
-MethodBind *godot_icall_Object_ClassDB_get_method(StringName *p_type, MonoString *p_method) {
- StringName type = p_type ? *p_type : StringName();
- StringName method(GDMonoMarshal::mono_string_to_godot(p_method));
- return ClassDB::get_method(type, method);
-}
-
MonoObject *godot_icall_Object_weakref(Object *p_ptr) {
if (!p_ptr) {
return nullptr;
@@ -240,11 +226,9 @@ MonoString *godot_icall_Object_ToString(Object *p_ptr) {
}
void godot_register_object_icalls() {
- GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Ctor", godot_icall_Object_Ctor);
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_ClassDB_get_method", godot_icall_Object_ClassDB_get_method);
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);
@@ -253,5 +237,3 @@ void godot_register_object_icalls() {
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_GetMember", godot_icall_DynamicGodotObject_GetMember);
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMember", godot_icall_DynamicGodotObject_SetMember);
}
-
-#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp
index 8a9f30459c..30adea60cc 100644
--- a/modules/mono/glue/collections_glue.cpp
+++ b/modules/mono/glue/collections_glue.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 */
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef MONO_GLUE_ENABLED
-
#include <mono/metadata/exception.h>
#include "core/variant/array.h"
@@ -39,28 +37,17 @@
#include "../mono_gd/gd_mono_marshal.h"
#include "../mono_gd/gd_mono_utils.h"
-Array *godot_icall_Array_Ctor() {
- return memnew(Array);
-}
-
-void godot_icall_Array_Dtor(Array *ptr) {
- memdelete(ptr);
-}
-
-MonoObject *godot_icall_Array_At(Array *ptr, int32_t index) {
- if (index < 0 || index >= ptr->size()) {
- GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
- return nullptr;
- }
- return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index));
+void godot_icall_Array_Ctor(Array *r_dest) {
+ memnew_placement(r_dest, Array);
}
-MonoObject *godot_icall_Array_At_Generic(Array *ptr, int32_t index, uint32_t type_encoding, GDMonoClass *type_class) {
+void godot_icall_Array_At(Array *ptr, int32_t index, Variant *r_elem) {
if (index < 0 || index >= ptr->size()) {
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
- return nullptr;
+ *r_elem = Variant();
+ return;
}
- return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index), ManagedType(type_encoding, type_class));
+ *r_elem = ptr->operator[](index);
}
void godot_icall_Array_SetAt(Array *ptr, int32_t index, MonoObject *value) {
@@ -104,29 +91,27 @@ void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int32_t array_index)
}
}
-Array *godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array) {
- Array *godot_array = memnew(Array);
+void godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array, Array *r_dest) {
+ memnew_placement(r_dest, Array);
unsigned int count = mono_array_length(mono_array);
- godot_array->resize(count);
+ r_dest->resize(count);
for (unsigned int i = 0; i < count; i++) {
MonoObject *item = mono_array_get(mono_array, MonoObject *, i);
- godot_icall_Array_SetAt(godot_array, i, item);
+ godot_icall_Array_SetAt(r_dest, i, item);
}
- return godot_array;
}
-Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep) {
- return memnew(Array(ptr->duplicate(deep)));
+void godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep, Array *r_dest) {
+ memnew_placement(r_dest, Array(ptr->duplicate(deep)));
}
-Array *godot_icall_Array_Concatenate(Array *left, Array *right) {
+void godot_icall_Array_Concatenate(Array *left, Array *right, Array *r_dest) {
int count = left->size() + right->size();
- Array *new_array = memnew(Array(left->duplicate(false)));
- new_array->resize(count);
+ memnew_placement(r_dest, Array(left->duplicate(false)));
+ r_dest->resize(count);
for (unsigned int i = 0; i < (unsigned int)right->size(); i++) {
- new_array->operator[](i + left->size()) = right->operator[](i);
+ r_dest->operator[](i + left->size()) = right->operator[](i);
}
- return new_array;
}
int32_t godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) {
@@ -166,41 +151,15 @@ void godot_icall_Array_Shuffle(Array *ptr) {
ptr->shuffle();
}
-void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
- MonoType *elem_type = mono_reflection_type_get_type(refltype);
-
- *type_encoding = mono_type_get_type(elem_type);
- MonoClass *type_class_raw = mono_class_from_mono_type(elem_type);
- *type_class = GDMono::get_singleton()->get_class(type_class_raw);
-}
-
MonoString *godot_icall_Array_ToString(Array *ptr) {
return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
}
-Dictionary *godot_icall_Dictionary_Ctor() {
- return memnew(Dictionary);
-}
-
-void godot_icall_Dictionary_Dtor(Dictionary *ptr) {
- memdelete(ptr);
-}
-
-MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
- Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
- if (ret == nullptr) {
- MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
-#ifdef DEBUG_ENABLED
- CRASH_COND(!exc);
-#endif
- GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
- GDMonoUtils::set_pending_exception((MonoException *)exc);
- return nullptr;
- }
- return GDMonoMarshal::variant_to_mono_object(ret);
+void godot_icall_Dictionary_Ctor(Dictionary *r_dest) {
+ memnew_placement(r_dest, Dictionary);
}
-MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject *key, uint32_t type_encoding, GDMonoClass *type_class) {
+void godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key, Variant *r_value) {
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
if (ret == nullptr) {
MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
@@ -209,42 +168,37 @@ MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject
#endif
GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
GDMonoUtils::set_pending_exception((MonoException *)exc);
- return nullptr;
+ *r_value = Variant();
+ return;
}
- return GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
+ *r_value = *ret;
}
void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value) {
ptr->operator[](GDMonoMarshal::mono_object_to_variant(key)) = GDMonoMarshal::mono_object_to_variant(value);
}
-Array *godot_icall_Dictionary_Keys(Dictionary *ptr) {
- return memnew(Array(ptr->keys()));
+void godot_icall_Dictionary_Keys(Dictionary *ptr, Array *r_dest) {
+ memnew_placement(r_dest, Array(ptr->keys()));
}
-Array *godot_icall_Dictionary_Values(Dictionary *ptr) {
- return memnew(Array(ptr->values()));
+void godot_icall_Dictionary_Values(Dictionary *ptr, Array *r_dest) {
+ memnew_placement(r_dest, Array(ptr->values()));
}
int32_t godot_icall_Dictionary_Count(Dictionary *ptr) {
return ptr->size();
}
-int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array **keys, Array **values) {
- *keys = godot_icall_Dictionary_Keys(ptr);
- *values = godot_icall_Dictionary_Values(ptr);
- return godot_icall_Dictionary_Count(ptr);
-}
-
-void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, MonoObject **key, MonoObject **value) {
- *key = GDMonoMarshal::variant_to_mono_object(ptr->get_key_at_index(index));
- *value = GDMonoMarshal::variant_to_mono_object(ptr->get_value_at_index(index));
+int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array *keys, Array *values) {
+ memnew_placement(keys, Array(ptr->keys()));
+ memnew_placement(values, Array(ptr->values()));
+ return ptr->size();
}
-void godot_icall_Dictionary_KeyValuePairAt_Generic(Dictionary *ptr, int index, MonoObject **key, MonoObject **value, uint32_t value_type_encoding, GDMonoClass *value_type_class) {
- ManagedType type(value_type_encoding, value_type_class);
- *key = GDMonoMarshal::variant_to_mono_object(ptr->get_key_at_index(index));
- *value = GDMonoMarshal::variant_to_mono_object(ptr->get_value_at_index(index), type);
+void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, Variant *r_key, Variant *r_value) {
+ memnew_placement(r_key, Variant(ptr->get_key_at_index(index)));
+ memnew_placement(r_value, Variant(ptr->get_value_at_index(index)));
}
void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
@@ -271,8 +225,8 @@ MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key)
return ptr->has(GDMonoMarshal::mono_object_to_variant(key));
}
-Dictionary *godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep) {
- return memnew(Dictionary(ptr->duplicate(deep)));
+void godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep, Dictionary *r_dest) {
+ memnew_placement(r_dest, Dictionary(ptr->duplicate(deep)));
}
MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
@@ -292,34 +246,16 @@ MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, Mono
return false;
}
-MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
- Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
- if (ret == nullptr) {
- *value = nullptr;
- return false;
- }
- *value = GDMonoMarshal::variant_to_mono_object(ret);
- return true;
-}
-
-MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
+MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, Variant *value) {
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
if (ret == nullptr) {
- *value = nullptr;
+ *value = Variant();
return false;
}
- *value = GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
+ *value = *ret;
return true;
}
-void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
- MonoType *value_type = mono_reflection_type_get_type(refltype);
-
- *type_encoding = mono_type_get_type(value_type);
- MonoClass *type_class_raw = mono_class_from_mono_type(value_type);
- *type_class = GDMono::get_singleton()->get_class(type_class_raw);
-}
-
MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) {
return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
}
@@ -327,9 +263,7 @@ MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) {
void godot_register_collections_icalls() {
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", godot_icall_Array_Ctor);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor_MonoArray", godot_icall_Array_Ctor_MonoArray);
- GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", godot_icall_Array_Dtor);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At", godot_icall_Array_At);
- GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At_Generic", godot_icall_Array_At_Generic);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", godot_icall_Array_SetAt);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", godot_icall_Array_Count);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", godot_icall_Array_Add);
@@ -344,20 +278,16 @@ void godot_register_collections_icalls() {
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", godot_icall_Array_RemoveAt);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Resize", godot_icall_Array_Resize);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Shuffle", godot_icall_Array_Shuffle);
- GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Generic_GetElementTypeInfo", godot_icall_Array_Generic_GetElementTypeInfo);
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_ToString", godot_icall_Array_ToString);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", godot_icall_Dictionary_Ctor);
- GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", godot_icall_Dictionary_Dtor);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", godot_icall_Dictionary_GetValue);
- GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue_Generic", godot_icall_Dictionary_GetValue_Generic);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", godot_icall_Dictionary_SetValue);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", godot_icall_Dictionary_Keys);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", godot_icall_Dictionary_Values);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt);
- GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt_Generic", godot_icall_Dictionary_KeyValuePairAt_Generic);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains);
@@ -366,9 +296,5 @@ void godot_register_collections_icalls() {
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", godot_icall_Dictionary_RemoveKey);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", godot_icall_Dictionary_Remove);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", godot_icall_Dictionary_TryGetValue);
- GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue_Generic", godot_icall_Dictionary_TryGetValue_Generic);
- GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Generic_GetValueTypeInfo", godot_icall_Dictionary_Generic_GetValueTypeInfo);
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ToString", godot_icall_Dictionary_ToString);
}
-
-#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp
index 8b1c2b729e..b315831819 100644
--- a/modules/mono/glue/gd_glue.cpp
+++ b/modules/mono/glue/gd_glue.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef MONO_GLUE_ENABLED
-
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
@@ -41,10 +39,9 @@
#include "../mono_gd/gd_mono_marshal.h"
#include "../mono_gd/gd_mono_utils.h"
-MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects) {
+MonoObject *godot_icall_GD_bytes2var(PackedByteArray *p_bytes, MonoBoolean p_allow_objects) {
Variant ret;
- PackedByteArray varr = GDMonoMarshal::mono_array_to_PackedByteArray(p_bytes);
- Error err = decode_variant(ret, varr.ptr(), varr.size(), nullptr, p_allow_objects);
+ 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.");
}
@@ -285,18 +282,17 @@ void godot_icall_GD_pushwarning(MonoString *p_str) {
WARN_PRINT(GDMonoMarshal::mono_string_to_godot(p_str));
}
-MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects) {
+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);
- PackedByteArray barr;
int len;
Error err = encode_variant(var, nullptr, len, p_full_objects);
- ERR_FAIL_COND_V_MSG(err != OK, nullptr, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
+ ERR_FAIL_COND_MSG(err != OK, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
- barr.resize(len);
- encode_variant(var, barr.ptrw(), len, p_full_objects);
-
- return GDMonoMarshal::PackedByteArray_to_mono_array(barr);
+ r_bytes->resize(len);
+ encode_variant(var, r_bytes->ptrw(), len, p_full_objects);
}
MonoString *godot_icall_GD_var2str(MonoObject *p_var) {
@@ -344,5 +340,3 @@ void godot_register_gd_icalls() {
// Dispatcher
GDMonoUtils::add_internal_call("Godot.Dispatcher::godot_icall_DefaultGodotTaskScheduler", godot_icall_DefaultGodotTaskScheduler);
}
-
-#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
deleted file mode 100644
index f9ad1a9893..0000000000
--- a/modules/mono/glue/glue_header.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*************************************************************************/
-/* glue_header.h */
-/*************************************************************************/
-/* 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. */
-/*************************************************************************/
-
-#ifndef GLUE_HEADER_H
-#define GLUE_HEADER_H
-
-#ifdef MONO_GLUE_ENABLED
-
-#include "../mono_gd/gd_mono_marshal.h"
-
-void godot_register_collections_icalls();
-void godot_register_gd_icalls();
-void godot_register_string_name_icalls();
-void godot_register_nodepath_icalls();
-void godot_register_callable_icalls();
-void godot_register_object_icalls();
-void godot_register_rid_icalls();
-void godot_register_string_icalls();
-void godot_register_scene_tree_icalls();
-
-/**
- * Registers internal calls that were not generated. This function is called
- * from the generated GodotSharpBindings::register_generated_icalls() function.
- */
-void godot_register_glue_header_icalls() {
- godot_register_collections_icalls();
- godot_register_gd_icalls();
- godot_register_string_name_icalls();
- godot_register_nodepath_icalls();
- godot_register_callable_icalls();
- godot_register_object_icalls();
- godot_register_rid_icalls();
- godot_register_string_icalls();
- godot_register_scene_tree_icalls();
-}
-
-// Used by the generated glue
-
-#include "core/config/engine.h"
-#include "core/object/class_db.h"
-#include "core/object/method_bind.h"
-#include "core/object/ref_counted.h"
-#include "core/string/node_path.h"
-#include "core/string/ustring.h"
-#include "core/typedefs.h"
-#include "core/variant/array.h"
-#include "core/variant/dictionary.h"
-
-#include "../mono_gd/gd_mono_class.h"
-#include "../mono_gd/gd_mono_internals.h"
-#include "../mono_gd/gd_mono_utils.h"
-
-#define GODOTSHARP_INSTANCE_OBJECT(m_instance, m_type) \
- static ClassDB::ClassInfo *ci = nullptr; \
- if (!ci) { \
- ci = ClassDB::classes.getptr(m_type); \
- } \
- Object *m_instance = ci->creation_func();
-
-#include "arguments_vector.h"
-
-#endif // MONO_GLUE_ENABLED
-
-#endif // GLUE_HEADER_H
diff --git a/modules/mono/glue/nodepath_glue.cpp b/modules/mono/glue/node_path_glue.cpp
index 16e1509eb0..770ed31260 100644
--- a/modules/mono/glue/nodepath_glue.cpp
+++ b/modules/mono/glue/node_path_glue.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* nodepath_glue.cpp */
+/* node_path_glue.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,26 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef MONO_GLUE_ENABLED
-
#include "core/string/node_path.h"
#include "core/string/ustring.h"
#include "../mono_gd/gd_mono_marshal.h"
-NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) {
- return memnew(NodePath(GDMonoMarshal::mono_string_to_godot(p_path)));
-}
-
-void godot_icall_NodePath_Dtor(NodePath *p_ptr) {
- ERR_FAIL_NULL(p_ptr);
- memdelete(p_ptr);
-}
-
-MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) {
- return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
-}
-
MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) {
return (MonoBoolean)p_ptr->is_absolute();
}
@@ -76,18 +61,11 @@ MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) {
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames());
}
-NodePath *godot_icall_NodePath_get_as_property_path(NodePath *p_ptr) {
- return memnew(NodePath(p_ptr->get_as_property_path()));
+void godot_icall_NodePath_get_as_property_path(NodePath *p_ptr, NodePath *r_dest) {
+ *r_dest = p_ptr->get_as_property_path();
}
-MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr) {
- return (MonoBoolean)p_ptr->is_empty();
-}
-
-void godot_register_nodepath_icalls() {
- GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Ctor", godot_icall_NodePath_Ctor);
- GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", godot_icall_NodePath_Dtor);
- GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", godot_icall_NodePath_operator_String);
+void godot_register_node_path_icalls() {
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_names", godot_icall_NodePath_get_concatenated_names);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames);
@@ -96,7 +74,4 @@ void godot_register_nodepath_icalls() {
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname", godot_icall_NodePath_get_subname);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname_count", godot_icall_NodePath_get_subname_count);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_is_absolute", godot_icall_NodePath_is_absolute);
- GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_is_empty", godot_icall_NodePath_is_empty);
}
-
-#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/rid_glue.cpp b/modules/mono/glue/placeholder_glue.cpp
index 3e09564539..edac231bb4 100644
--- a/modules/mono/glue/rid_glue.cpp
+++ b/modules/mono/glue/placeholder_glue.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* rid_glue.cpp */
+/* placeholder_glue.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,37 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef MONO_GLUE_ENABLED
+#ifndef GLUE_HEADER_H
+#define GLUE_HEADER_H
-#include "core/io/resource.h"
-#include "core/object/class_db.h"
-#include "core/templates/rid.h"
+#include "core/object/object.h"
-#include "../mono_gd/gd_mono_marshal.h"
+#include "../mono_gd/gd_mono_internals.h"
+#include "../mono_gd/gd_mono_utils.h"
-RID *godot_icall_RID_Ctor(Object *p_from) {
- Resource *res_from = Object::cast_to<Resource>(p_from);
-
- if (res_from) {
- return memnew(RID(res_from->get_rid()));
- }
-
- return memnew(RID);
-}
-
-void godot_icall_RID_Dtor(RID *p_ptr) {
- ERR_FAIL_NULL(p_ptr);
- memdelete(p_ptr);
+MonoObject *godot_icall_InteropUtils_unmanaged_get_managed(Object *unmanaged) {
+ return GDMonoUtils::unmanaged_get_managed(unmanaged);
}
-uint32_t godot_icall_RID_get_id(RID *p_ptr) {
- return p_ptr->get_id();
+void godot_icall_InteropUtils_tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
+ GDMonoInternals::tie_managed_to_unmanaged(managed, unmanaged);
}
-void godot_register_rid_icalls() {
- GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_Ctor", godot_icall_RID_Ctor);
- GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_Dtor", godot_icall_RID_Dtor);
- GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_get_id", godot_icall_RID_get_id);
+void godot_register_placeholder_icalls() {
+ GDMonoUtils::add_internal_call(
+ "Godot.NativeInterop.InteropUtils::internal_unmanaged_get_managed",
+ godot_icall_InteropUtils_unmanaged_get_managed);
+ GDMonoUtils::add_internal_call(
+ "Godot.NativeInterop.InteropUtils::internal_tie_managed_to_unmanaged",
+ godot_icall_InteropUtils_tie_managed_to_unmanaged);
}
-#endif // MONO_GLUE_ENABLED
+#endif // GLUE_HEADER_H
diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp
new file mode 100644
index 0000000000..a9c47f8880
--- /dev/null
+++ b/modules/mono/glue/runtime_interop.cpp
@@ -0,0 +1,786 @@
+/*************************************************************************/
+/* runtime_interop.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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/config/engine.h"
+#include "core/object/class_db.h"
+#include "core/object/method_bind.h"
+#include "core/string/string_name.h"
+
+#include "../interop_types.h"
+
+#include "modules/mono/managed_callable.h"
+#include "modules/mono/signal_awaiter_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+#define MAYBE_UNUSED [[maybe_unused]]
+#else
+#define MAYBE_UNUSED
+#endif
+
+#ifdef __GNUC__
+#define GD_PINVOKE_EXPORT MAYBE_UNUSED __attribute__((visibility("default")))
+#elif defined(_WIN32)
+#define GD_PINVOKE_EXPORT MAYBE_UNUSED __declspec(dllexport)
+#else
+#define GD_PINVOKE_EXPORT MAYBE_UNUSED
+#endif
+
+typedef Object *(*godotsharp_class_creation_func)();
+
+GD_PINVOKE_EXPORT MethodBind *godotsharp_method_bind_get_method(const StringName *p_classname, const char16_t *p_methodname) {
+ return ClassDB::get_method(*p_classname, StringName(String::utf16(p_methodname)));
+}
+
+GD_PINVOKE_EXPORT godotsharp_class_creation_func godotsharp_get_class_constructor(const StringName *p_classname) {
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(*p_classname);
+ if (class_info) {
+ return class_info->creation_func;
+ }
+ return nullptr;
+}
+
+GD_PINVOKE_EXPORT Object *godotsharp_invoke_class_constructor(godotsharp_class_creation_func p_creation_func) {
+ return p_creation_func();
+}
+
+GD_PINVOKE_EXPORT Object *godotsharp_engine_get_singleton(const String *p_name) {
+ return Engine::get_singleton()->get_singleton_object(*p_name);
+}
+
+GD_PINVOKE_EXPORT void godotsharp_ref_destroy(Ref<RefCounted> *p_instance) {
+ p_instance->~Ref();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_string_name_new_from_string(StringName *r_dest, const String *p_name) {
+ memnew_placement(r_dest, StringName(*p_name));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_node_path_new_from_string(NodePath *r_dest, const String *p_name) {
+ memnew_placement(r_dest, NodePath(*p_name));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_string_name_as_string(String *r_dest, const StringName *p_name) {
+ memnew_placement(r_dest, String(p_name->operator String()));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_node_path_as_string(String *r_dest, const NodePath *p_np) {
+ memnew_placement(r_dest, String(p_np->operator String()));
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_byte_array_new_mem_copy(const uint8_t *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedByteArray);
+ PackedByteArray *array = reinterpret_cast<PackedByteArray *>(&ret);
+ array->resize(p_length);
+ uint8_t *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(uint8_t));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_int32_array_new_mem_copy(const int32_t *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedInt32Array);
+ PackedInt32Array *array = reinterpret_cast<PackedInt32Array *>(&ret);
+ array->resize(p_length);
+ int32_t *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(int32_t));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_int64_array_new_mem_copy(const int64_t *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedInt64Array);
+ PackedInt64Array *array = reinterpret_cast<PackedInt64Array *>(&ret);
+ array->resize(p_length);
+ int64_t *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(int64_t));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_float32_array_new_mem_copy(const float *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedFloat32Array);
+ PackedFloat32Array *array = reinterpret_cast<PackedFloat32Array *>(&ret);
+ array->resize(p_length);
+ float *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(float));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_float64_array_new_mem_copy(const double *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedFloat64Array);
+ PackedFloat64Array *array = reinterpret_cast<PackedFloat64Array *>(&ret);
+ array->resize(p_length);
+ double *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(double));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_vector2_array_new_mem_copy(const Vector2 *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedVector2Array);
+ PackedVector2Array *array = reinterpret_cast<PackedVector2Array *>(&ret);
+ array->resize(p_length);
+ Vector2 *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(Vector2));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_vector3_array_new_mem_copy(const Vector3 *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedVector3Array);
+ PackedVector3Array *array = reinterpret_cast<PackedVector3Array *>(&ret);
+ array->resize(p_length);
+ Vector3 *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(Vector3));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_packed_color_array_new_mem_copy(const Color *p_src, int32_t p_length) {
+ godot_packed_array ret;
+ memnew_placement(&ret, PackedColorArray);
+ PackedColorArray *array = reinterpret_cast<PackedColorArray *>(&ret);
+ array->resize(p_length);
+ Color *dst = array->ptrw();
+ memcpy(dst, p_src, p_length * sizeof(Color));
+ return ret;
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_string_array_add(PackedStringArray *r_dest, const String *p_element) {
+ r_dest->append(*p_element);
+}
+
+GD_PINVOKE_EXPORT void godotsharp_callable_new_with_delegate(void *p_delegate_handle, Callable *r_callable) {
+ // TODO: Use pooling for ManagedCallable instances.
+ CallableCustom *managed_callable = memnew(ManagedCallable(p_delegate_handle));
+ *r_callable = Callable(managed_callable);
+}
+
+GD_PINVOKE_EXPORT bool godotsharp_callable_get_data_for_marshalling(const Callable *p_callable,
+ void **r_delegate_handle, Object **r_object, StringName *r_name) {
+ if (p_callable->is_custom()) {
+ CallableCustom *custom = p_callable->get_custom();
+ CallableCustom::CompareEqualFunc compare_equal_func = custom->get_compare_equal_func();
+
+ if (compare_equal_func == ManagedCallable::compare_equal_func_ptr) {
+ ManagedCallable *managed_callable = static_cast<ManagedCallable *>(custom);
+ *r_delegate_handle = managed_callable->get_delegate();
+ *r_object = nullptr;
+ *r_name = StringName();
+ return true;
+ } else if (compare_equal_func == SignalAwaiterCallable::compare_equal_func_ptr) {
+ SignalAwaiterCallable *signal_awaiter_callable = static_cast<SignalAwaiterCallable *>(custom);
+ *r_delegate_handle = nullptr;
+ *r_object = ObjectDB::get_instance(signal_awaiter_callable->get_object());
+ *r_name = signal_awaiter_callable->get_signal();
+ return true;
+ } else if (compare_equal_func == EventSignalCallable::compare_equal_func_ptr) {
+ EventSignalCallable *event_signal_callable = static_cast<EventSignalCallable *>(custom);
+ *r_delegate_handle = nullptr;
+ *r_object = ObjectDB::get_instance(event_signal_callable->get_object());
+ *r_name = event_signal_callable->get_signal();
+ return true;
+ }
+
+ // Some other CallableCustom. We only support ManagedCallable.
+ *r_delegate_handle = nullptr;
+ *r_object = nullptr;
+ *r_name = StringName();
+ return false;
+ } else {
+ *r_delegate_handle = nullptr;
+ *r_object = ObjectDB::get_instance(p_callable->get_object_id());
+ *r_name = p_callable->get_method();
+ return true;
+ }
+}
+
+// GDNative functions
+
+// gdnative.h
+
+GD_PINVOKE_EXPORT void godotsharp_method_bind_ptrcall(MethodBind *p_method_bind, Object *p_instance, const void **p_args, void *p_ret) {
+ p_method_bind->ptrcall(p_instance, p_args, p_ret);
+}
+
+GD_PINVOKE_EXPORT godot_variant godotsharp_method_bind_call(MethodBind *p_method_bind, Object *p_instance, const godot_variant **p_args, const int p_arg_count, Callable::CallError *p_call_error) {
+ godot_variant ret;
+ memnew_placement(&ret, Variant());
+
+ Variant *ret_val = (Variant *)&ret;
+
+ *ret_val = p_method_bind->call(p_instance, (const Variant **)p_args, p_arg_count, *p_call_error);
+
+ return ret;
+}
+
+// variant.h
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_string_name(godot_variant *r_dest, const StringName *p_s) {
+ memnew_placement(r_dest, Variant(*p_s));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_node_path(godot_variant *r_dest, const NodePath *p_np) {
+ memnew_placement(r_dest, Variant(*p_np));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_object(godot_variant *r_dest, const Object *p_obj) {
+ memnew_placement(r_dest, Variant(p_obj));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_transform2d(godot_variant *r_dest, const Transform2D *p_t2d) {
+ memnew_placement(r_dest, Variant(*p_t2d));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_vector4(godot_variant *r_dest, const Vector4 *p_vec4) {
+ memnew_placement(r_dest, Variant(*p_vec4));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_vector4i(godot_variant *r_dest, const Vector4i *p_vec4i) {
+ memnew_placement(r_dest, Variant(*p_vec4i));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_basis(godot_variant *r_dest, const Basis *p_basis) {
+ memnew_placement(r_dest, Variant(*p_basis));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_transform3d(godot_variant *r_dest, const Transform3D *p_trans) {
+ memnew_placement(r_dest, Variant(*p_trans));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_projection(godot_variant *r_dest, const Projection *p_proj) {
+ memnew_placement(r_dest, Variant(*p_proj));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_aabb(godot_variant *r_dest, const AABB *p_aabb) {
+ memnew_placement(r_dest, Variant(*p_aabb));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_dictionary(godot_variant *r_dest, const Dictionary *p_dict) {
+ memnew_placement(r_dest, Variant(*p_dict));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_array(godot_variant *r_dest, const Array *p_arr) {
+ memnew_placement(r_dest, Variant(*p_arr));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_byte_array(godot_variant *r_dest, const PackedByteArray *p_pba) {
+ memnew_placement(r_dest, Variant(*p_pba));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_int32_array(godot_variant *r_dest, const PackedInt32Array *p_pia) {
+ memnew_placement(r_dest, Variant(*p_pia));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_int64_array(godot_variant *r_dest, const PackedInt64Array *p_pia) {
+ memnew_placement(r_dest, Variant(*p_pia));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_float32_array(godot_variant *r_dest, const PackedFloat32Array *p_pra) {
+ memnew_placement(r_dest, Variant(*p_pra));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_float64_array(godot_variant *r_dest, const PackedFloat64Array *p_pra) {
+ memnew_placement(r_dest, Variant(*p_pra));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_string_array(godot_variant *r_dest, const PackedStringArray *p_psa) {
+ memnew_placement(r_dest, Variant(*p_psa));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_vector2_array(godot_variant *r_dest, const PackedVector2Array *p_pv2a) {
+ memnew_placement(r_dest, Variant(*p_pv2a));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_vector3_array(godot_variant *r_dest, const PackedVector3Array *p_pv3a) {
+ memnew_placement(r_dest, Variant(*p_pv3a));
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_color_array(godot_variant *r_dest, const PackedColorArray *p_pca) {
+ memnew_placement(r_dest, Variant(*p_pca));
+}
+
+GD_PINVOKE_EXPORT bool godotsharp_variant_as_bool(const Variant *p_self) {
+ return p_self->operator bool();
+}
+
+GD_PINVOKE_EXPORT int64_t godotsharp_variant_as_int(const Variant *p_self) {
+ return p_self->operator int64_t();
+}
+
+GD_PINVOKE_EXPORT double godotsharp_variant_as_float(const Variant *p_self) {
+ return p_self->operator double();
+}
+
+GD_PINVOKE_EXPORT godot_string godotsharp_variant_as_string(const Variant *p_self) {
+ godot_string raw_dest;
+ String *dest = (String *)&raw_dest;
+ memnew_placement(dest, String(p_self->operator String()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_vector2 godotsharp_variant_as_vector2(const Variant *p_self) {
+ godot_vector2 raw_dest;
+ Vector2 *dest = (Vector2 *)&raw_dest;
+ memnew_placement(dest, Vector2(p_self->operator Vector2()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_vector2i godotsharp_variant_as_vector2i(const Variant *p_self) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ memnew_placement(dest, Vector2i(p_self->operator Vector2i()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_rect2 godotsharp_variant_as_rect2(const Variant *p_self) {
+ godot_rect2 raw_dest;
+ Rect2 *dest = (Rect2 *)&raw_dest;
+ memnew_placement(dest, Rect2(p_self->operator Rect2()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_rect2i godotsharp_variant_as_rect2i(const Variant *p_self) {
+ godot_rect2i raw_dest;
+ Rect2i *dest = (Rect2i *)&raw_dest;
+ memnew_placement(dest, Rect2i(p_self->operator Rect2i()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_vector3 godotsharp_variant_as_vector3(const Variant *p_self) {
+ godot_vector3 raw_dest;
+ Vector3 *dest = (Vector3 *)&raw_dest;
+ memnew_placement(dest, Vector3(p_self->operator Vector3()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_vector3i godotsharp_variant_as_vector3i(const Variant *p_self) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ memnew_placement(dest, Vector3i(p_self->operator Vector3i()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_transform2d godotsharp_variant_as_transform2d(const Variant *p_self) {
+ godot_transform2d raw_dest;
+ Transform2D *dest = (Transform2D *)&raw_dest;
+ memnew_placement(dest, Transform2D(p_self->operator Transform2D()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_vector4 godotsharp_variant_as_vector4(const Variant *p_self) {
+ godot_vector4 raw_dest;
+ Vector4 *dest = (Vector4 *)&raw_dest;
+ memnew_placement(dest, Vector4(p_self->operator Vector4()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_vector4i godotsharp_variant_as_vector4i(const Variant *p_self) {
+ godot_vector4i raw_dest;
+ Vector4i *dest = (Vector4i *)&raw_dest;
+ memnew_placement(dest, Vector4i(p_self->operator Vector4i()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_plane godotsharp_variant_as_plane(const Variant *p_self) {
+ godot_plane raw_dest;
+ Plane *dest = (Plane *)&raw_dest;
+ memnew_placement(dest, Plane(p_self->operator Plane()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_quaternion godotsharp_variant_as_quaternion(const Variant *p_self) {
+ godot_quaternion raw_dest;
+ Quaternion *dest = (Quaternion *)&raw_dest;
+ memnew_placement(dest, Quaternion(p_self->operator Quaternion()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_aabb godotsharp_variant_as_aabb(const Variant *p_self) {
+ godot_aabb raw_dest;
+ AABB *dest = (AABB *)&raw_dest;
+ memnew_placement(dest, AABB(p_self->operator ::AABB()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_basis godotsharp_variant_as_basis(const Variant *p_self) {
+ godot_basis raw_dest;
+ Basis *dest = (Basis *)&raw_dest;
+ memnew_placement(dest, Basis(p_self->operator Basis()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_transform3d godotsharp_variant_as_transform3d(const Variant *p_self) {
+ godot_transform3d raw_dest;
+ Transform3D *dest = (Transform3D *)&raw_dest;
+ memnew_placement(dest, Transform3D(p_self->operator Transform3D()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_projection godotsharp_variant_as_projection(const Variant *p_self) {
+ godot_projection raw_dest;
+ Projection *dest = (Projection *)&raw_dest;
+ memnew_placement(dest, Projection(p_self->operator Projection()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_color godotsharp_variant_as_color(const Variant *p_self) {
+ godot_color raw_dest;
+ Color *dest = (Color *)&raw_dest;
+ memnew_placement(dest, Color(p_self->operator Color()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_string_name godotsharp_variant_as_string_name(const Variant *p_self) {
+ godot_string_name raw_dest;
+ StringName *dest = (StringName *)&raw_dest;
+ memnew_placement(dest, StringName(p_self->operator StringName()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_node_path godotsharp_variant_as_node_path(const Variant *p_self) {
+ godot_node_path raw_dest;
+ NodePath *dest = (NodePath *)&raw_dest;
+ memnew_placement(dest, NodePath(p_self->operator NodePath()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_rid godotsharp_variant_as_rid(const Variant *p_self) {
+ godot_rid raw_dest;
+ RID *dest = (RID *)&raw_dest;
+ memnew_placement(dest, RID(p_self->operator ::RID()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_callable godotsharp_variant_as_callable(const Variant *p_self) {
+ godot_callable raw_dest;
+ Callable *dest = (Callable *)&raw_dest;
+ memnew_placement(dest, Callable(p_self->operator Callable()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_signal godotsharp_variant_as_signal(const Variant *p_self) {
+ godot_signal raw_dest;
+ Signal *dest = (Signal *)&raw_dest;
+ memnew_placement(dest, Signal(p_self->operator Signal()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_dictionary godotsharp_variant_as_dictionary(const Variant *p_self) {
+ godot_dictionary raw_dest;
+ Dictionary *dest = (Dictionary *)&raw_dest;
+ memnew_placement(dest, Dictionary(p_self->operator Dictionary()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_array godotsharp_variant_as_array(const Variant *p_self) {
+ godot_array raw_dest;
+ Array *dest = (Array *)&raw_dest;
+ memnew_placement(dest, Array(p_self->operator Array()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_byte_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedByteArray *dest = (PackedByteArray *)&raw_dest;
+ memnew_placement(dest, PackedByteArray(p_self->operator PackedByteArray()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_int32_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedInt32Array *dest = (PackedInt32Array *)&raw_dest;
+ memnew_placement(dest, PackedInt32Array(p_self->operator PackedInt32Array()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_int64_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedInt64Array *dest = (PackedInt64Array *)&raw_dest;
+ memnew_placement(dest, PackedInt64Array(p_self->operator PackedInt64Array()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_float32_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedFloat32Array *dest = (PackedFloat32Array *)&raw_dest;
+ memnew_placement(dest, PackedFloat32Array(p_self->operator PackedFloat32Array()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_float64_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedFloat64Array *dest = (PackedFloat64Array *)&raw_dest;
+ memnew_placement(dest, PackedFloat64Array(p_self->operator PackedFloat64Array()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_string_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedStringArray *dest = (PackedStringArray *)&raw_dest;
+ memnew_placement(dest, PackedStringArray(p_self->operator PackedStringArray()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_vector2_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedVector2Array *dest = (PackedVector2Array *)&raw_dest;
+ memnew_placement(dest, PackedVector2Array(p_self->operator PackedVector2Array()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_vector3_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedVector3Array *dest = (PackedVector3Array *)&raw_dest;
+ memnew_placement(dest, PackedVector3Array(p_self->operator PackedVector3Array()));
+ return raw_dest;
+}
+
+GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_color_array(const Variant *p_self) {
+ godot_packed_array raw_dest;
+ PackedColorArray *dest = (PackedColorArray *)&raw_dest;
+ memnew_placement(dest, PackedColorArray(p_self->operator PackedColorArray()));
+ return raw_dest;
+}
+
+// string.h
+
+GD_PINVOKE_EXPORT void godotsharp_string_new_with_utf16_chars(String *r_dest, const char16_t *p_contents) {
+ memnew_placement(r_dest, String());
+ r_dest->parse_utf16(p_contents);
+}
+
+// string_name.h
+
+GD_PINVOKE_EXPORT void godotsharp_string_name_new_copy(StringName *r_dest, const StringName *p_src) {
+ memnew_placement(r_dest, StringName(*p_src));
+}
+
+// node_path.h
+
+GD_PINVOKE_EXPORT void godotsharp_node_path_new_copy(NodePath *r_dest, const NodePath *p_src) {
+ memnew_placement(r_dest, NodePath(*p_src));
+}
+
+// array.h
+
+GD_PINVOKE_EXPORT void godotsharp_array_new_copy(Array *r_dest, const Array *p_src) {
+ memnew_placement(r_dest, Array(*p_src));
+}
+
+// dictionary.h
+
+GD_PINVOKE_EXPORT void godotsharp_dictionary_new_copy(Dictionary *r_dest, const Dictionary *p_src) {
+ memnew_placement(r_dest, Dictionary(*p_src));
+}
+
+// destroy functions
+
+GD_PINVOKE_EXPORT void godotsharp_packed_byte_array_destroy(PackedByteArray *p_self) {
+ p_self->~PackedByteArray();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_int32_array_destroy(PackedInt32Array *p_self) {
+ p_self->~PackedInt32Array();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_int64_array_destroy(PackedInt64Array *p_self) {
+ p_self->~PackedInt64Array();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_float32_array_destroy(PackedFloat32Array *p_self) {
+ p_self->~PackedFloat32Array();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_float64_array_destroy(PackedFloat64Array *p_self) {
+ p_self->~PackedFloat64Array();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_string_array_destroy(PackedStringArray *p_self) {
+ p_self->~PackedStringArray();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_vector2_array_destroy(PackedVector2Array *p_self) {
+ p_self->~PackedVector2Array();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_vector3_array_destroy(PackedVector3Array *p_self) {
+ p_self->~PackedVector3Array();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_packed_color_array_destroy(PackedColorArray *p_self) {
+ p_self->~PackedColorArray();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_variant_destroy(Variant *p_self) {
+ p_self->~Variant();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_string_destroy(String *p_self) {
+ p_self->~String();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_string_name_destroy(StringName *p_self) {
+ p_self->~StringName();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_node_path_destroy(NodePath *p_self) {
+ p_self->~NodePath();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_signal_destroy(Signal *p_self) {
+ p_self->~Signal();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_callable_destroy(Callable *p_self) {
+ p_self->~Callable();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_array_destroy(Array *p_self) {
+ p_self->~Array();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_dictionary_destroy(Dictionary *p_self) {
+ p_self->~Dictionary();
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+// We need this to prevent the functions from being stripped.
+void *godotsharp_pinvoke_funcs[101] = {
+ (void *)godotsharp_method_bind_get_method,
+ (void *)godotsharp_get_class_constructor,
+ (void *)godotsharp_invoke_class_constructor,
+ (void *)godotsharp_engine_get_singleton,
+ (void *)godotsharp_ref_destroy,
+ (void *)godotsharp_string_name_new_from_string,
+ (void *)godotsharp_node_path_new_from_string,
+ (void *)godotsharp_string_name_as_string,
+ (void *)godotsharp_node_path_as_string,
+ (void *)godotsharp_packed_byte_array_new_mem_copy,
+ (void *)godotsharp_packed_int32_array_new_mem_copy,
+ (void *)godotsharp_packed_int64_array_new_mem_copy,
+ (void *)godotsharp_packed_float32_array_new_mem_copy,
+ (void *)godotsharp_packed_float64_array_new_mem_copy,
+ (void *)godotsharp_packed_vector2_array_new_mem_copy,
+ (void *)godotsharp_packed_vector3_array_new_mem_copy,
+ (void *)godotsharp_packed_color_array_new_mem_copy,
+ (void *)godotsharp_packed_string_array_add,
+ (void *)godotsharp_callable_new_with_delegate,
+ (void *)godotsharp_callable_get_data_for_marshalling,
+ (void *)godotsharp_method_bind_ptrcall,
+ (void *)godotsharp_method_bind_call,
+ (void *)godotsharp_variant_new_string_name,
+ (void *)godotsharp_variant_new_node_path,
+ (void *)godotsharp_variant_new_object,
+ (void *)godotsharp_variant_new_transform2d,
+ (void *)godotsharp_variant_new_vector4,
+ (void *)godotsharp_variant_new_vector4i,
+ (void *)godotsharp_variant_new_basis,
+ (void *)godotsharp_variant_new_transform3d,
+ (void *)godotsharp_variant_new_projection,
+ (void *)godotsharp_variant_new_aabb,
+ (void *)godotsharp_variant_new_dictionary,
+ (void *)godotsharp_variant_new_array,
+ (void *)godotsharp_variant_new_packed_byte_array,
+ (void *)godotsharp_variant_new_packed_int32_array,
+ (void *)godotsharp_variant_new_packed_int64_array,
+ (void *)godotsharp_variant_new_packed_float32_array,
+ (void *)godotsharp_variant_new_packed_float64_array,
+ (void *)godotsharp_variant_new_packed_string_array,
+ (void *)godotsharp_variant_new_packed_vector2_array,
+ (void *)godotsharp_variant_new_packed_vector3_array,
+ (void *)godotsharp_variant_new_packed_color_array,
+ (void *)godotsharp_variant_as_bool,
+ (void *)godotsharp_variant_as_int,
+ (void *)godotsharp_variant_as_float,
+ (void *)godotsharp_variant_as_string,
+ (void *)godotsharp_variant_as_vector2,
+ (void *)godotsharp_variant_as_vector2i,
+ (void *)godotsharp_variant_as_rect2,
+ (void *)godotsharp_variant_as_rect2i,
+ (void *)godotsharp_variant_as_vector3,
+ (void *)godotsharp_variant_as_vector3i,
+ (void *)godotsharp_variant_as_transform2d,
+ (void *)godotsharp_variant_as_vector4,
+ (void *)godotsharp_variant_as_vector4i,
+ (void *)godotsharp_variant_as_plane,
+ (void *)godotsharp_variant_as_quaternion,
+ (void *)godotsharp_variant_as_aabb,
+ (void *)godotsharp_variant_as_basis,
+ (void *)godotsharp_variant_as_transform3d,
+ (void *)godotsharp_variant_as_projection,
+ (void *)godotsharp_variant_as_color,
+ (void *)godotsharp_variant_as_string_name,
+ (void *)godotsharp_variant_as_node_path,
+ (void *)godotsharp_variant_as_rid,
+ (void *)godotsharp_variant_as_callable,
+ (void *)godotsharp_variant_as_signal,
+ (void *)godotsharp_variant_as_dictionary,
+ (void *)godotsharp_variant_as_array,
+ (void *)godotsharp_variant_as_packed_byte_array,
+ (void *)godotsharp_variant_as_packed_int32_array,
+ (void *)godotsharp_variant_as_packed_int64_array,
+ (void *)godotsharp_variant_as_packed_float32_array,
+ (void *)godotsharp_variant_as_packed_float64_array,
+ (void *)godotsharp_variant_as_packed_string_array,
+ (void *)godotsharp_variant_as_packed_vector2_array,
+ (void *)godotsharp_variant_as_packed_vector3_array,
+ (void *)godotsharp_variant_as_packed_color_array,
+ (void *)godotsharp_string_new_with_utf16_chars,
+ (void *)godotsharp_string_name_new_copy,
+ (void *)godotsharp_node_path_new_copy,
+ (void *)godotsharp_array_new_copy,
+ (void *)godotsharp_dictionary_new_copy,
+ (void *)godotsharp_packed_byte_array_destroy,
+ (void *)godotsharp_packed_int32_array_destroy,
+ (void *)godotsharp_packed_int64_array_destroy,
+ (void *)godotsharp_packed_float32_array_destroy,
+ (void *)godotsharp_packed_float64_array_destroy,
+ (void *)godotsharp_packed_string_array_destroy,
+ (void *)godotsharp_packed_vector2_array_destroy,
+ (void *)godotsharp_packed_vector3_array_destroy,
+ (void *)godotsharp_packed_color_array_destroy,
+ (void *)godotsharp_variant_destroy,
+ (void *)godotsharp_string_destroy,
+ (void *)godotsharp_string_name_destroy,
+ (void *)godotsharp_node_path_destroy,
+ (void *)godotsharp_signal_destroy,
+ (void *)godotsharp_callable_destroy,
+ (void *)godotsharp_array_destroy,
+ (void *)godotsharp_dictionary_destroy
+};
diff --git a/modules/mono/glue/scene_tree_glue.cpp b/modules/mono/glue/scene_tree_glue.cpp
index c60e7c4869..55a46ad368 100644
--- a/modules/mono/glue/scene_tree_glue.cpp
+++ b/modules/mono/glue/scene_tree_glue.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef MONO_GLUE_ENABLED
-
#include "core/object/class_db.h"
#include "core/string/string_name.h"
#include "core/variant/array.h"
@@ -40,9 +38,10 @@
#include "../mono_gd/gd_mono_marshal.h"
#include "../mono_gd/gd_mono_utils.h"
-Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringName *group, MonoReflectionType *refltype) {
+void godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringName *group, MonoReflectionType *refltype, Array *r_dest) {
+ memnew_placement(r_dest, Array);
+
List<Node *> nodes;
- Array ret;
// Retrieve all the nodes in the group
ptr->get_nodes_in_group(*group, &nodes);
@@ -58,7 +57,7 @@ Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringNa
StringName native_class_name = GDMonoUtils::get_native_godot_class_name(klass);
for (int i = 0; i < nodes.size(); ++i) {
if (ClassDB::is_parent_class(nodes[i]->get_class(), native_class_name)) {
- ret.push_back(nodes[i]);
+ r_dest->push_back(nodes[i]);
}
}
} else {
@@ -69,18 +68,14 @@ Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringNa
if (si != nullptr) {
MonoObject *obj = si->get_mono_object();
if (obj != nullptr && mono_object_get_class(obj) == mono_class) {
- ret.push_back(nodes[i]);
+ r_dest->push_back(nodes[i]);
}
}
}
}
}
-
- return memnew(Array(ret));
}
void godot_register_scene_tree_icalls() {
GDMonoUtils::add_internal_call("Godot.SceneTree::godot_icall_SceneTree_get_nodes_in_group_Generic", godot_icall_SceneTree_get_nodes_in_group_Generic);
}
-
-#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/string_glue.cpp b/modules/mono/glue/string_glue.cpp
index fc6b13ceb3..fe1c0b5f8c 100644
--- a/modules/mono/glue/string_glue.cpp
+++ b/modules/mono/glue/string_glue.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef MONO_GLUE_ENABLED
-
#include "core/string/ustring.h"
#include "core/templates/vector.h"
#include "core/variant/variant.h"
@@ -81,5 +79,3 @@ void godot_register_string_icalls() {
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_sha256_text", godot_icall_String_sha256_text);
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_simplify_path", godot_icall_String_simplify_path);
}
-
-#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/string_name_glue.cpp b/modules/mono/glue/string_name_glue.cpp
deleted file mode 100644
index 46d15316ba..0000000000
--- a/modules/mono/glue/string_name_glue.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*************************************************************************/
-/* string_name_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. */
-/*************************************************************************/
-
-#ifdef MONO_GLUE_ENABLED
-
-#include "core/string/string_name.h"
-#include "core/string/ustring.h"
-
-#include "../mono_gd/gd_mono_marshal.h"
-
-StringName *godot_icall_StringName_Ctor(MonoString *p_path) {
- return memnew(StringName(GDMonoMarshal::mono_string_to_godot(p_path)));
-}
-
-void godot_icall_StringName_Dtor(StringName *p_ptr) {
- ERR_FAIL_NULL(p_ptr);
- memdelete(p_ptr);
-}
-
-MonoString *godot_icall_StringName_operator_String(StringName *p_np) {
- return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
-}
-
-MonoBoolean godot_icall_StringName_is_empty(StringName *p_ptr) {
- return (MonoBoolean)(*p_ptr == StringName());
-}
-
-void godot_register_string_name_icalls() {
- GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_Ctor", godot_icall_StringName_Ctor);
- GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_Dtor", godot_icall_StringName_Dtor);
- GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_operator_String", godot_icall_StringName_operator_String);
- GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_is_empty", godot_icall_StringName_is_empty);
-}
-
-#endif // MONO_GLUE_ENABLED