summaryrefslogtreecommitdiff
path: root/modules/mono/glue
diff options
context:
space:
mode:
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