Przeglądaj źródła

C#: Code cleanup and greatly reduce use of C# pointers

Ignacio Roldán Etcheverry 3 lat temu
rodzic
commit
e5e7a795b1
51 zmienionych plików z 2127 dodań i 1297 usunięć
  1. 29 0
      modules/mono/.editorconfig
  2. 3 0
      modules/mono/.gitignore
  3. 1 1
      modules/mono/csharp_script.cpp
  4. 2 2
      modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
  5. 2 0
      modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj
  6. 5 5
      modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
  7. 7 7
      modules/mono/editor/GodotTools/GodotTools/Internals/EditorProgress.cs
  8. 11 11
      modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
  9. 7 7
      modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs
  10. 5 5
      modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
  11. 3 3
      modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
  12. 103 78
      modules/mono/editor/bindings_generator.cpp
  13. 18 5
      modules/mono/editor/bindings_generator.h
  14. 8 0
      modules/mono/glue/GodotSharp/.editorconfig
  15. 91 51
      modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
  16. 4 4
      modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
  17. 18 13
      modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs
  18. 22 19
      modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
  19. 61 5
      modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs
  20. 4 4
      modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
  21. 7 7
      modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs
  22. 3 3
      modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
  23. 121 84
      modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
  24. 6 9
      modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs
  25. 8 10
      modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs
  26. 57 58
      modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
  27. 595 97
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
  28. 10 17
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs
  29. 252 255
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
  30. 196 168
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
  31. 19 42
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
  32. 20 0
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeVariantPtrArgs.cs
  33. 5 5
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs
  34. 162 188
      modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
  35. 38 32
      modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
  36. 26 27
      modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
  37. 2 2
      modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
  38. 8 6
      modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs
  39. 1 1
      modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
  40. 38 37
      modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
  41. 10 12
      modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs
  42. 2 2
      modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
  43. 6 6
      modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
  44. 2 2
      modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
  45. 2 2
      modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
  46. 2 2
      modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
  47. 2 2
      modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
  48. 3 0
      modules/mono/glue/GodotSharp/GodotSharp/FodyWeavers.xml
  49. 93 0
      modules/mono/glue/GodotSharp/GodotSharp/GenerateGodotCustomUnsafe.targets
  50. 9 0
      modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
  51. 18 1
      modules/mono/glue/runtime_interop.cpp

+ 29 - 0
modules/mono/.editorconfig

@@ -12,3 +12,32 @@ insert_final_newline = true
 trim_trailing_whitespace = true
 trim_trailing_whitespace = true
 max_line_length = 120
 max_line_length = 120
 csharp_indent_case_contents_when_block = false
 csharp_indent_case_contents_when_block = false
+
+[*.cs]
+# CA1707: Identifiers should not contain underscores
+# TODO:
+#  Maybe we could disable this selectively only
+#  where it's not desired and for generated code.
+dotnet_diagnostic.CA1707.severity = none
+# CA1711: Identifiers should not have incorrect suffix
+# Disable warning for suffixes like EventHandler, Flags, Enum, etc.
+dotnet_diagnostic.CA1711.severity = none
+# CA1716: Identifiers should not match keywords
+# TODO: We should look into this.
+dotnet_diagnostic.CA1716.severity = warning
+# CA1720: Identifiers should not contain type names
+dotnet_diagnostic.CA1720.severity = none
+# CA1805: Do not initialize unnecessarily
+# Don't tell me what to do.
+dotnet_diagnostic.CA1805.severity = none
+# CA1304: Specify CultureInfo
+# TODO: We should look into this.
+dotnet_diagnostic.CA1304.severity = warning
+# CA1305: Specify IFormatProvider
+# TODO: We should look into this. Disabled for now because it's annoying.
+dotnet_diagnostic.CA1305.severity = none
+# CA1310: Specify StringComparison for correctness
+# TODO: We should look into this. Disabled for now because it's annoying.
+dotnet_diagnostic.CA1310.severity = none
+# Diagnostics to prevent defensive copies of `in` struct parameters
+resharper_possibly_impure_method_call_on_readonly_variable_highlighting = error

+ 3 - 0
modules/mono/.gitignore

@@ -1,2 +1,5 @@
 # Do not ignore solution files inside the mono module. Overrides Godot's global gitignore.
 # Do not ignore solution files inside the mono module. Overrides Godot's global gitignore.
 !*.sln
 !*.sln
+
+# Fody
+FodyWeavers.xsd

+ 1 - 1
modules/mono/csharp_script.cpp

@@ -104,7 +104,7 @@ Error CSharpLanguage::execute_file(const String &p_path) {
 	return OK;
 	return OK;
 }
 }
 
 
-extern void *godotsharp_pinvoke_funcs[176];
+extern void *godotsharp_pinvoke_funcs[178];
 [[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
 [[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 extern void *godotsharp_editor_pinvoke_funcs[32];
 extern void *godotsharp_editor_pinvoke_funcs[32];

+ 2 - 2
modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets

@@ -8,8 +8,8 @@
   </Target>
   </Target>
 
 
   <Target Name="GenerateGodotNupkgsVersionsFile"
   <Target Name="GenerateGodotNupkgsVersionsFile"
-          DependsOnTargets="PrepareForBuild;_GenerateGodotNupkgsVersionsFile"
-          BeforeTargets="BeforeCompile;CoreCompile">
+          DependsOnTargets="_GenerateGodotNupkgsVersionsFile"
+          BeforeTargets="PrepareForBuild;CompileDesignTime;BeforeCompile;CoreCompile">
     <ItemGroup>
     <ItemGroup>
       <Compile Include="$(GeneratedGodotNupkgsVersionsFile)" />
       <Compile Include="$(GeneratedGodotNupkgsVersionsFile)" />
       <FileWrites Include="$(GeneratedGodotNupkgsVersionsFile)" />
       <FileWrites Include="$(GeneratedGodotNupkgsVersionsFile)" />

+ 2 - 0
modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj

@@ -1,6 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
 <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
     <PropertyGroup>
         <TargetFramework>net5.0</TargetFramework>
         <TargetFramework>net5.0</TargetFramework>
+        <!-- Specify compile items manually to avoid including dangling generated items. -->
+        <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
     </PropertyGroup>
     </PropertyGroup>
     <Import Project="GenerateGodotNupkgsVersions.targets" />
     <Import Project="GenerateGodotNupkgsVersions.targets" />
 </Project>
 </Project>

+ 5 - 5
modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs

@@ -233,11 +233,11 @@ namespace GodotTools.Export
                 }
                 }
             }
             }
 
 
-            var initialAssemblies = assemblies.Duplicate();
-            godot_dictionary initialAssembliesAux = ((Godot.Collections.Dictionary)initialAssemblies).NativeValue;
-            using godot_string buildConfigAux = Marshaling.mono_string_to_godot(buildConfig);
-            using godot_string bclDirAux = Marshaling.mono_string_to_godot(bclDir);
-            godot_dictionary assembliesAux = ((Godot.Collections.Dictionary)assemblies).NativeValue;
+            // var initialAssemblies = assemblies.Duplicate();
+            // godot_dictionary initialAssembliesAux = ((Godot.Collections.Dictionary)initialAssemblies).NativeValue;
+            // using godot_string buildConfigAux = Marshaling.ConvertStringToNative(buildConfig);
+            // using godot_string bclDirAux = Marshaling.ConvertStringToNative(bclDir);
+            // godot_dictionary assembliesAux = ((Godot.Collections.Dictionary)assemblies).NativeValue;
             // TODO
             // TODO
             throw new NotImplementedException();
             throw new NotImplementedException();
             //internal_GetExportedAssemblyDependencies(initialAssembliesAux, buildConfigAux, bclDirAux, ref assembliesAux);
             //internal_GetExportedAssemblyDependencies(initialAssembliesAux, buildConfigAux, bclDirAux, ref assembliesAux);

+ 7 - 7
modules/mono/editor/GodotTools/GodotTools/Internals/EditorProgress.cs

@@ -12,8 +12,8 @@ namespace GodotTools.Internals
         public EditorProgress(string task, string label, int amount, bool canCancel = false)
         public EditorProgress(string task, string label, int amount, bool canCancel = false)
         {
         {
             Task = task;
             Task = task;
-            using godot_string taskIn = Marshaling.mono_string_to_godot(task);
-            using godot_string labelIn = Marshaling.mono_string_to_godot(label);
+            using godot_string taskIn = Marshaling.ConvertStringToNative(task);
+            using godot_string labelIn = Marshaling.ConvertStringToNative(label);
             Internal.godot_icall_EditorProgress_Create(taskIn, labelIn, amount, canCancel);
             Internal.godot_icall_EditorProgress_Create(taskIn, labelIn, amount, canCancel);
         }
         }
 
 
@@ -27,22 +27,22 @@ namespace GodotTools.Internals
 
 
         public void Dispose()
         public void Dispose()
         {
         {
-            using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
+            using godot_string taskIn = Marshaling.ConvertStringToNative(Task);
             Internal.godot_icall_EditorProgress_Dispose(taskIn);
             Internal.godot_icall_EditorProgress_Dispose(taskIn);
             GC.SuppressFinalize(this);
             GC.SuppressFinalize(this);
         }
         }
 
 
         public void Step(string state, int step = -1, bool forceRefresh = true)
         public void Step(string state, int step = -1, bool forceRefresh = true)
         {
         {
-            using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
-            using godot_string stateIn = Marshaling.mono_string_to_godot(state);
+            using godot_string taskIn = Marshaling.ConvertStringToNative(Task);
+            using godot_string stateIn = Marshaling.ConvertStringToNative(state);
             Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
             Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
         }
         }
 
 
         public bool TryStep(string state, int step = -1, bool forceRefresh = true)
         public bool TryStep(string state, int step = -1, bool forceRefresh = true)
         {
         {
-            using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
-            using godot_string stateIn = Marshaling.mono_string_to_godot(state);
+            using godot_string taskIn = Marshaling.ConvertStringToNative(Task);
+            using godot_string stateIn = Marshaling.ConvertStringToNative(state);
             return Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
             return Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
         }
         }
     }
     }

+ 11 - 11
modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs

@@ -10,37 +10,37 @@ namespace GodotTools.Internals
 
 
         public static unsafe object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false)
         public static unsafe object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false)
         {
         {
-            using godot_string settingIn = Marshaling.mono_string_to_godot(setting);
-            using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue);
+            using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
+            using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue);
             Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
             Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
             using (result)
             using (result)
-                return Marshaling.variant_to_mono_object(&result);
+                return Marshaling.ConvertVariantToManagedObject(result);
         }
         }
 
 
         public static unsafe object EditorDef(string setting, object defaultValue, bool restartIfChanged = false)
         public static unsafe object EditorDef(string setting, object defaultValue, bool restartIfChanged = false)
         {
         {
-            using godot_string settingIn = Marshaling.mono_string_to_godot(setting);
-            using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue);
+            using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
+            using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue);
             Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
             Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
             using (result)
             using (result)
-                return Marshaling.variant_to_mono_object(&result);
+                return Marshaling.ConvertVariantToManagedObject(result);
         }
         }
 
 
-        public static unsafe object EditorShortcut(string setting)
+        public static object EditorShortcut(string setting)
         {
         {
-            using godot_string settingIn = Marshaling.mono_string_to_godot(setting);
+            using godot_string settingIn = Marshaling.ConvertStringToNative(setting);
             Internal.godot_icall_Globals_EditorShortcut(settingIn, out godot_variant result);
             Internal.godot_icall_Globals_EditorShortcut(settingIn, out godot_variant result);
             using (result)
             using (result)
-                return Marshaling.variant_to_mono_object(&result);
+                return Marshaling.ConvertVariantToManagedObject(result);
         }
         }
 
 
         [SuppressMessage("ReSharper", "InconsistentNaming")]
         [SuppressMessage("ReSharper", "InconsistentNaming")]
         public static string TTR(this string text)
         public static string TTR(this string text)
         {
         {
-            using godot_string textIn = Marshaling.mono_string_to_godot(text);
+            using godot_string textIn = Marshaling.ConvertStringToNative(text);
             Internal.godot_icall_Globals_TTR(textIn, out godot_string dest);
             Internal.godot_icall_Globals_TTR(textIn, out godot_string dest);
             using (dest)
             using (dest)
-                return Marshaling.mono_string_from_godot(dest);
+                return Marshaling.ConvertStringToManaged(dest);
         }
         }
     }
     }
 }
 }

+ 7 - 7
modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs

@@ -11,7 +11,7 @@ namespace GodotTools.Internals
             {
             {
                 Internal.godot_icall_GodotSharpDirs_ResMetadataDir(out godot_string dest);
                 Internal.godot_icall_GodotSharpDirs_ResMetadataDir(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -21,7 +21,7 @@ namespace GodotTools.Internals
             {
             {
                 Internal.godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(out godot_string dest);
                 Internal.godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -31,7 +31,7 @@ namespace GodotTools.Internals
             {
             {
                 Internal.godot_icall_GodotSharpDirs_MonoUserDir(out godot_string dest);
                 Internal.godot_icall_GodotSharpDirs_MonoUserDir(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -41,7 +41,7 @@ namespace GodotTools.Internals
             {
             {
                 Internal.godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string dest);
                 Internal.godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -51,7 +51,7 @@ namespace GodotTools.Internals
             {
             {
                 Internal.godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string dest);
                 Internal.godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -61,7 +61,7 @@ namespace GodotTools.Internals
             {
             {
                 Internal.godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string dest);
                 Internal.godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -71,7 +71,7 @@ namespace GodotTools.Internals
             {
             {
                 Internal.godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string dest);
                 Internal.godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
     }
     }

+ 5 - 5
modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs

@@ -18,7 +18,7 @@ namespace GodotTools.Internals
             {
             {
                 godot_icall_Internal_FullExportTemplatesDir(out godot_string dest);
                 godot_icall_Internal_FullExportTemplatesDir(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -26,7 +26,7 @@ namespace GodotTools.Internals
 
 
         public static bool IsMacOSAppBundleInstalled(string bundleId)
         public static bool IsMacOSAppBundleInstalled(string bundleId)
         {
         {
-            using godot_string bundleIdIn = Marshaling.mono_string_to_godot(bundleId);
+            using godot_string bundleIdIn = Marshaling.ConvertStringToNative(bundleId);
             return godot_icall_Internal_IsMacOSAppBundleInstalled(bundleIdIn);
             return godot_icall_Internal_IsMacOSAppBundleInstalled(bundleIdIn);
         }
         }
 
 
@@ -53,7 +53,7 @@ namespace GodotTools.Internals
             {
             {
                 godot_icall_Internal_MonoWindowsInstallRoot(out godot_string dest);
                 godot_icall_Internal_MonoWindowsInstallRoot(out godot_string dest);
                 using (dest)
                 using (dest)
-                    return Marshaling.mono_string_from_godot(dest);
+                    return Marshaling.ConvertStringToManaged(dest);
             }
             }
         }
         }
 
 
@@ -67,10 +67,10 @@ namespace GodotTools.Internals
         public static unsafe string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind,
         public static unsafe string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind,
             string scriptFile)
             string scriptFile)
         {
         {
-            using godot_string scriptFileIn = Marshaling.mono_string_to_godot(scriptFile);
+            using godot_string scriptFileIn = Marshaling.ConvertStringToNative(scriptFile);
             godot_icall_Internal_CodeCompletionRequest((int)kind, scriptFileIn, out godot_packed_string_array res);
             godot_icall_Internal_CodeCompletionRequest((int)kind, scriptFileIn, out godot_packed_string_array res);
             using (res)
             using (res)
-                return Marshaling.PackedStringArray_to_mono_array(&res);
+                return Marshaling.ConvertNativePackedStringArrayToSystemArray(res);
         }
         }
 
 
         #region Internal
         #region Internal

+ 3 - 3
modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs

@@ -63,7 +63,7 @@ namespace GodotTools.Utils
             Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
             Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
             using (dest)
             using (dest)
             {
             {
-                string platformName = Marshaling.mono_string_from_godot(dest);
+                string platformName = Marshaling.ConvertStringToManaged(dest);
                 return name.Equals(platformName, StringComparison.OrdinalIgnoreCase);
                 return name.Equals(platformName, StringComparison.OrdinalIgnoreCase);
             }
             }
         }
         }
@@ -73,7 +73,7 @@ namespace GodotTools.Utils
             Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
             Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
             using (dest)
             using (dest)
             {
             {
-                string platformName = Marshaling.mono_string_from_godot(dest);
+                string platformName = Marshaling.ConvertStringToManaged(dest);
                 return names.Any(p => p.Equals(platformName, StringComparison.OrdinalIgnoreCase));
                 return names.Any(p => p.Equals(platformName, StringComparison.OrdinalIgnoreCase));
             }
             }
         }
         }
@@ -185,7 +185,7 @@ namespace GodotTools.Utils
             return searchDirs.Select(dir => Path.Combine(dir, name))
             return searchDirs.Select(dir => Path.Combine(dir, name))
                 .FirstOrDefault(path =>
                 .FirstOrDefault(path =>
                 {
                 {
-                    using godot_string pathIn = Marshaling.mono_string_to_godot(path);
+                    using godot_string pathIn = Marshaling.ConvertStringToNative(path);
                     return File.Exists(path) && Internal.godot_icall_Utils_OS_UnixFileHasExecutableAccess(pathIn);
                     return File.Exists(path) && Internal.godot_icall_Utils_OS_UnixFileHasExecutableAccess(pathIn);
                 });
                 });
         }
         }

+ 103 - 78
modules/mono/editor/bindings_generator.cpp

@@ -101,12 +101,12 @@ StringBuilder &operator<<(StringBuilder &r_sb, const char *p_cstring) {
 #define C_METHOD_ENGINE_GET_SINGLETON C_NS_MONOUTILS ".EngineGetSingleton"
 #define C_METHOD_ENGINE_GET_SINGLETON C_NS_MONOUTILS ".EngineGetSingleton"
 
 
 #define C_NS_MONOMARSHAL "Marshaling"
 #define C_NS_MONOMARSHAL "Marshaling"
-#define C_METHOD_MANAGED_TO_VARIANT C_NS_MONOMARSHAL ".mono_object_to_variant"
-#define C_METHOD_MANAGED_FROM_VARIANT C_NS_MONOMARSHAL ".variant_to_mono_object"
-#define C_METHOD_MONOSTR_TO_GODOT C_NS_MONOMARSHAL ".mono_string_to_godot"
-#define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL ".mono_string_from_godot"
-#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL ".mono_array_to_" #m_type
-#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "." #m_type "_to_mono_array"
+#define C_METHOD_MANAGED_TO_VARIANT C_NS_MONOMARSHAL ".ConvertManagedObjectToVariant"
+#define C_METHOD_MANAGED_FROM_VARIANT C_NS_MONOMARSHAL ".ConvertVariantToManagedObject"
+#define C_METHOD_MONOSTR_TO_GODOT C_NS_MONOMARSHAL ".ConvertStringToNative"
+#define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL ".ConvertStringToManaged"
+#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL ".ConvertSystemArrayToNative" #m_type
+#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL ".ConvertNative" #m_type "ToSystemArray"
 #define C_METHOD_MANAGED_TO_CALLABLE C_NS_MONOMARSHAL ".ConvertCallableToNative"
 #define C_METHOD_MANAGED_TO_CALLABLE C_NS_MONOMARSHAL ".ConvertCallableToNative"
 #define C_METHOD_MANAGED_FROM_CALLABLE C_NS_MONOMARSHAL ".ConvertCallableToManaged"
 #define C_METHOD_MANAGED_FROM_CALLABLE C_NS_MONOMARSHAL ".ConvertCallableToManaged"
 #define C_METHOD_MANAGED_TO_SIGNAL C_NS_MONOMARSHAL ".ConvertSignalToNative"
 #define C_METHOD_MANAGED_TO_SIGNAL C_NS_MONOMARSHAL ".ConvertSignalToNative"
@@ -122,7 +122,7 @@ void BindingsGenerator::TypeInterface::postsetup_enum_type(BindingsGenerator::Ty
 	// any of the changes done here to the 'uint32_t' type interface as well.
 	// any of the changes done here to the 'uint32_t' type interface as well.
 
 
 	r_enum_itype.cs_type = r_enum_itype.proxy_name;
 	r_enum_itype.cs_type = r_enum_itype.proxy_name;
-	r_enum_itype.cs_in = "(int)%s";
+	r_enum_itype.cs_in_expr = "(int)%0";
 	r_enum_itype.cs_out = "%5return (%2)%0(%1);";
 	r_enum_itype.cs_out = "%5return (%2)%0(%1);";
 
 
 	{
 	{
@@ -391,23 +391,23 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
 				xml_output.append(tag);
 				xml_output.append(tag);
 				xml_output.append("</c>");
 				xml_output.append("</c>");
 			} else if (tag == "PackedByteArray") {
 			} else if (tag == "PackedByteArray") {
-				xml_output.append("<see cref=\"T:byte[]\"/>");
+				xml_output.append("<see cref=\"byte\"/>[]");
 			} else if (tag == "PackedInt32Array") {
 			} else if (tag == "PackedInt32Array") {
-				xml_output.append("<see cref=\"T:int[]\"/>");
+				xml_output.append("<see cref=\"int\"/>[]");
 			} else if (tag == "PackedInt64Array") {
 			} else if (tag == "PackedInt64Array") {
-				xml_output.append("<see cref=\"T:long[]\"/>");
+				xml_output.append("<see cref=\"long\"/>[]");
 			} else if (tag == "PackedFloat32Array") {
 			} else if (tag == "PackedFloat32Array") {
-				xml_output.append("<see cref=\"T:float[]\"/>");
+				xml_output.append("<see cref=\"float\"/>[]");
 			} else if (tag == "PackedFloat64Array") {
 			} else if (tag == "PackedFloat64Array") {
-				xml_output.append("<see cref=\"T:double[]\"/>");
+				xml_output.append("<see cref=\"double\"/>[]");
 			} else if (tag == "PackedStringArray") {
 			} else if (tag == "PackedStringArray") {
-				xml_output.append("<see cref=\"T:string[]\"/>");
+				xml_output.append("<see cref=\"string\"/>[]");
 			} else if (tag == "PackedVector2Array") {
 			} else if (tag == "PackedVector2Array") {
-				xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Vector2[]\"/>");
+				xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector2\"/>[]");
 			} else if (tag == "PackedVector3Array") {
 			} else if (tag == "PackedVector3Array") {
-				xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Vector3[]\"/>");
+				xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector3\"/>[]");
 			} else if (tag == "PackedColorArray") {
 			} else if (tag == "PackedColorArray") {
-				xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Color[]\"/>");
+				xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Color\"/>[]");
 			} else {
 			} else {
 				const TypeInterface *target_itype = _get_type_or_null(TypeReference(tag));
 				const TypeInterface *target_itype = _get_type_or_null(TypeReference(tag));
 
 
@@ -1380,6 +1380,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 				  "#pragma warning disable CS1573 // Disable warning: "
 				  "#pragma warning disable CS1573 // Disable warning: "
 				  "'Parameter has no matching param tag in the XML comment'\n");
 				  "'Parameter has no matching param tag in the XML comment'\n");
 
 
+	output.append("\n#nullable disable\n");
+
 	output.append("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
 	output.append("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
 
 
 	const DocData::ClassDoc *class_doc = itype.class_doc;
 	const DocData::ClassDoc *class_doc = itype.class_doc;
@@ -1413,20 +1415,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 	}
 	}
 	output.append(itype.proxy_name);
 	output.append(itype.proxy_name);
 
 
-	if (itype.is_singleton) {
-		output.append("\n");
-	} else if (is_derived_type) {
+	if (is_derived_type && !itype.is_singleton) {
 		if (obj_types.has(itype.base_name)) {
 		if (obj_types.has(itype.base_name)) {
 			output.append(" : ");
 			output.append(" : ");
 			output.append(obj_types[itype.base_name].proxy_name);
 			output.append(obj_types[itype.base_name].proxy_name);
-			output.append("\n");
 		} else {
 		} else {
 			ERR_PRINT("Base type '" + itype.base_name.operator String() + "' does not exist, for class '" + itype.name + "'.");
 			ERR_PRINT("Base type '" + itype.base_name.operator String() + "' does not exist, for class '" + itype.name + "'.");
 			return ERR_INVALID_DATA;
 			return ERR_INVALID_DATA;
 		}
 		}
 	}
 	}
 
 
-	output.append(INDENT1 "{");
+	output.append("\n" INDENT1 "{");
 
 
 	// Add constants
 	// Add constants
 
 
@@ -1546,7 +1545,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 			// Add native constructor static field
 			// Add native constructor static field
 
 
 			output << MEMBER_BEGIN << "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
 			output << MEMBER_BEGIN << "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
-				   << INDENT2 "private static unsafe readonly delegate* unmanaged<IntPtr> "
+				   << INDENT2 "private static readonly unsafe delegate* unmanaged<IntPtr> "
 				   << CS_STATIC_FIELD_NATIVE_CTOR " = " ICALL_CLASSDB_GET_CONSTRUCTOR
 				   << CS_STATIC_FIELD_NATIVE_CTOR " = " ICALL_CLASSDB_GET_CONSTRUCTOR
 				   << "(" BINDINGS_NATIVE_NAME_FIELD ");\n";
 				   << "(" BINDINGS_NATIVE_NAME_FIELD ");\n";
 		}
 		}
@@ -1608,7 +1607,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 		// TODO: string is ok for now. But should be replaced with StringName in the future for performance.
 		// TODO: string is ok for now. But should be replaced with StringName in the future for performance.
 
 
 		output << MEMBER_BEGIN "internal " << (is_derived_type ? "override" : "virtual")
 		output << MEMBER_BEGIN "internal " << (is_derived_type ? "override" : "virtual")
-			   << " unsafe bool InternalGodotScriptCall(string method, godot_variant** args, "
+			   << " bool InternalGodotScriptCall(string method, NativeVariantPtrArgs args, "
 			   << "int argCount, out godot_variant ret)\n"
 			   << "int argCount, out godot_variant ret)\n"
 			   << INDENT2 "{\n";
 			   << INDENT2 "{\n";
 
 
@@ -1646,10 +1645,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 				if (arg_type->cname == name_cache.type_Array_generic || arg_type->cname == name_cache.type_Dictionary_generic) {
 				if (arg_type->cname == name_cache.type_Array_generic || arg_type->cname == name_cache.type_Dictionary_generic) {
 					String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
 					String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
 
 
-					output << "new " << arg_cs_type << "((" << arg_type->cs_type << ")Marshaling.variant_to_mono_object_of_type(args["
+					output << "new " << arg_cs_type << "((" << arg_type->cs_type << ")Marshaling.ConvertVariantToManagedObjectOfType(args["
 						   << itos(i) << "], typeof(" << arg_type->cs_type << ")))";
 						   << itos(i) << "], typeof(" << arg_type->cs_type << ")))";
 				} else {
 				} else {
-					output << "(" << arg_type->cs_type << ")Marshaling.variant_to_mono_object_of_type(args["
+					output << "(" << arg_type->cs_type << ")Marshaling.ConvertVariantToManagedObjectOfType(args["
 						   << itos(i) << "], typeof(" << arg_type->cs_type << "))";
 						   << itos(i) << "], typeof(" << arg_type->cs_type << "))";
 				}
 				}
 			}
 			}
@@ -1658,7 +1657,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 
 
 			if (imethod.return_type.cname != name_cache.type_void) {
 			if (imethod.return_type.cname != name_cache.type_void) {
 				// TODO: static marshaling (no reflection, no runtime type checks)
 				// TODO: static marshaling (no reflection, no runtime type checks)
-				output << INDENT4 "ret = Marshaling.mono_object_to_variant(retBoxed);\n";
+				output << INDENT4 "ret = Marshaling.ConvertManagedObjectToVariant(retBoxed);\n";
 				output << INDENT4 "return true;\n";
 				output << INDENT4 "return true;\n";
 			} else {
 			} else {
 				output << INDENT4 "ret = default;\n";
 				output << INDENT4 "ret = default;\n";
@@ -1858,11 +1857,17 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 
 
 	String arguments_sig;
 	String arguments_sig;
 	StringBuilder cs_in_statements;
 	StringBuilder cs_in_statements;
-	bool cs_in_is_unsafe = false;
+	bool cs_in_expr_is_unsafe = false;
 
 
 	String icall_params = method_bind_field;
 	String icall_params = method_bind_field;
+
 	if (!p_imethod.is_static) {
 	if (!p_imethod.is_static) {
-		icall_params += ", " + sformat(p_itype.cs_in, "this");
+		if (p_itype.cs_in.size()) {
+			cs_in_statements << sformat(p_itype.cs_in, p_itype.c_type, "this",
+					String(), String(), String(), INDENT3);
+		}
+
+		icall_params += ", " + sformat(p_itype.cs_in_expr, "this");
 	}
 	}
 
 
 	StringBuilder default_args_doc;
 	StringBuilder default_args_doc;
@@ -1924,10 +1929,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 		if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) {
 		if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) {
 			// The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
 			// The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
 			// Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
 			// Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
-			String arg_in = iarg.name;
-			arg_in += "_in";
+			String arg_or_defval_local = iarg.name;
+			arg_or_defval_local += "OrDefVal";
 
 
-			cs_in_statements << INDENT3 << arg_cs_type << " " << arg_in << " = " << iarg.name;
+			cs_in_statements << INDENT3 << arg_cs_type << " " << arg_or_defval_local << " = " << iarg.name;
 
 
 			if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
 			if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
 				cs_in_statements << ".HasValue ? ";
 				cs_in_statements << ".HasValue ? ";
@@ -1952,7 +1957,16 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 
 
 			cs_in_statements << def_arg << ";\n";
 			cs_in_statements << def_arg << ";\n";
 
 
-			icall_params += arg_type->cs_in.is_empty() ? arg_in : sformat(arg_type->cs_in, arg_in);
+			if (arg_type->cs_in.size()) {
+				cs_in_statements << sformat(arg_type->cs_in, arg_type->c_type, arg_or_defval_local,
+						String(), String(), String(), INDENT3);
+			}
+
+			if (arg_type->cs_in_expr.is_empty()) {
+				icall_params += arg_or_defval_local;
+			} else {
+				icall_params += sformat(arg_type->cs_in_expr, arg_or_defval_local, arg_type->c_type);
+			}
 
 
 			// Apparently the name attribute must not include the @
 			// Apparently the name attribute must not include the @
 			String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name;
 			String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name;
@@ -1961,10 +1975,15 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 
 
 			default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is <c>" + param_def_arg + "</c>.</param>");
 			default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is <c>" + param_def_arg + "</c>.</param>");
 		} else {
 		} else {
-			icall_params += arg_type->cs_in.is_empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
+			if (arg_type->cs_in.size()) {
+				cs_in_statements << sformat(arg_type->cs_in, arg_type->c_type, iarg.name,
+						String(), String(), String(), INDENT3);
+			}
+
+			icall_params += arg_type->cs_in_expr.is_empty() ? iarg.name : sformat(arg_type->cs_in_expr, iarg.name, arg_type->c_type);
 		}
 		}
 
 
-		cs_in_is_unsafe |= arg_type->cs_in_is_unsafe;
+		cs_in_expr_is_unsafe |= arg_type->cs_in_expr_is_unsafe;
 	}
 	}
 
 
 	// Generate method
 	// Generate method
@@ -2034,7 +2053,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 			p_output.append("virtual ");
 			p_output.append("virtual ");
 		}
 		}
 
 
-		if (cs_in_is_unsafe) {
+		if (cs_in_expr_is_unsafe) {
 			p_output.append("unsafe ");
 			p_output.append("unsafe ");
 		}
 		}
 
 
@@ -2082,7 +2101,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 		im_call += ".";
 		im_call += ".";
 		im_call += im_icall->name;
 		im_call += im_icall->name;
 
 
-		if (p_imethod.arguments.size()) {
+		if (p_imethod.arguments.size() && cs_in_statements.get_string_length() > 0) {
 			p_output.append(cs_in_statements.as_string());
 			p_output.append(cs_in_statements.as_string());
 		}
 		}
 
 
@@ -2319,8 +2338,6 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
 
 
 	auto generate_call_and_return_stmts = [&](const char *base_indent) {
 	auto generate_call_and_return_stmts = [&](const char *base_indent) {
 		if (p_icall.is_vararg) {
 		if (p_icall.is_vararg) {
-			r_output << base_indent << "godot_variant_call_error vcall_error;\n";
-
 			// MethodBind Call
 			// MethodBind Call
 			r_output << base_indent;
 			r_output << base_indent;
 
 
@@ -2341,12 +2358,12 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
 			r_output << C_CLASS_NATIVE_FUNCS ".godotsharp_method_bind_call("
 			r_output << C_CLASS_NATIVE_FUNCS ".godotsharp_method_bind_call("
 					 << CS_PARAM_METHODBIND ", " << (p_icall.is_static ? "IntPtr.Zero" : CS_PARAM_INSTANCE)
 					 << CS_PARAM_METHODBIND ", " << (p_icall.is_static ? "IntPtr.Zero" : CS_PARAM_INSTANCE)
 					 << ", " << (p_icall.get_arguments_count() ? "(godot_variant**)" C_LOCAL_PTRCALL_ARGS : "null")
 					 << ", " << (p_icall.get_arguments_count() ? "(godot_variant**)" C_LOCAL_PTRCALL_ARGS : "null")
-					 << ", total_length, &vcall_error);\n";
+					 << ", total_length, out _);\n";
 
 
 			if (!ret_void) {
 			if (!ret_void) {
 				if (return_type->cname != name_cache.type_Variant) {
 				if (return_type->cname != name_cache.type_Variant) {
 					if (return_type->cname == name_cache.enum_Error) {
 					if (return_type->cname == name_cache.enum_Error) {
-						r_output << base_indent << C_LOCAL_RET " = VariantUtils.ConvertToInt64(&" C_LOCAL_VARARG_RET ");\n";
+						r_output << base_indent << C_LOCAL_RET " = VariantUtils.ConvertToInt64(" C_LOCAL_VARARG_RET ");\n";
 					} else {
 					} else {
 						// TODO: Use something similar to c_in_vararg (see usage above, with error if not implemented)
 						// TODO: Use something similar to c_in_vararg (see usage above, with error if not implemented)
 						CRASH_NOW_MSG("Custom VarArg return type not implemented: " + return_type->name);
 						CRASH_NOW_MSG("Custom VarArg return type not implemented: " + return_type->name);
@@ -2384,9 +2401,9 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
 			r_output << INDENT3 "int vararg_length = " << vararg_arg << ".Length;\n"
 			r_output << INDENT3 "int vararg_length = " << vararg_arg << ".Length;\n"
 					 << INDENT3 "int total_length = " << real_argc_str << " + vararg_length;\n";
 					 << INDENT3 "int total_length = " << real_argc_str << " + vararg_length;\n";
 
 
-			r_output << INDENT3 "Span<godot_variant> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n"
-					 << INDENT4 "stackalloc godot_variant[VarArgsSpanThreshold].Cleared() :\n"
-					 << INDENT4 "new godot_variant[vararg_length];\n";
+			r_output << INDENT3 "Span<godot_variant.movable> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n"
+					 << INDENT4 "stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :\n"
+					 << INDENT4 "new godot_variant.movable[vararg_length];\n";
 
 
 			r_output << INDENT3 "Span<IntPtr> " C_LOCAL_PTRCALL_ARGS "_span = total_length <= VarArgsSpanThreshold ?\n"
 			r_output << INDENT3 "Span<IntPtr> " C_LOCAL_PTRCALL_ARGS "_span = total_length <= VarArgsSpanThreshold ?\n"
 					 << INDENT4 "stackalloc IntPtr[VarArgsSpanThreshold] :\n"
 					 << INDENT4 "stackalloc IntPtr[VarArgsSpanThreshold] :\n"
@@ -2394,7 +2411,7 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
 
 
 			r_output << INDENT3 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n";
 			r_output << INDENT3 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n";
 
 
-			r_output << INDENT3 "fixed (godot_variant* varargs = &MemoryMarshal.GetReference(varargs_span))\n"
+			r_output << INDENT3 "fixed (godot_variant* varargs = &MemoryMarshal.GetReference(varargs_span).DangerousSelfRef)\n"
 					 << INDENT3 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = "
 					 << INDENT3 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = "
 								"&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n"
 								"&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n"
 					 << OPEN_BLOCK_L3;
 					 << OPEN_BLOCK_L3;
@@ -2678,14 +2695,14 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
 
 
 		itype.c_out = "%5return ";
 		itype.c_out = "%5return ";
 		itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
 		itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
-		itype.c_out += itype.is_ref_counted ? "(%1._reference);\n" : "(%1);\n";
+		itype.c_out += itype.is_ref_counted ? "(%1.Reference);\n" : "(%1);\n";
 
 
 		itype.cs_type = itype.proxy_name;
 		itype.cs_type = itype.proxy_name;
 
 
 		if (itype.is_singleton) {
 		if (itype.is_singleton) {
-			itype.cs_in = "Object." CS_STATIC_METHOD_GETINSTANCE "(" CS_PROPERTY_SINGLETON ")";
+			itype.cs_in_expr = "Object." CS_STATIC_METHOD_GETINSTANCE "(" CS_PROPERTY_SINGLETON ")";
 		} else {
 		} else {
-			itype.cs_in = "Object." CS_STATIC_METHOD_GETINSTANCE "(%0)";
+			itype.cs_in_expr = "Object." CS_STATIC_METHOD_GETINSTANCE "(%0)";
 		}
 		}
 
 
 		itype.cs_out = "%5return (%2)%0(%1);";
 		itype.cs_out = "%5return (%2)%0(%1);";
@@ -3128,8 +3145,13 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
 		case Variant::STRING_NAME:
 		case Variant::STRING_NAME:
 		case Variant::NODE_PATH:
 		case Variant::NODE_PATH:
 			if (r_iarg.type.cname == name_cache.type_StringName || r_iarg.type.cname == name_cache.type_NodePath) {
 			if (r_iarg.type.cname == name_cache.type_StringName || r_iarg.type.cname == name_cache.type_NodePath) {
-				r_iarg.default_argument = "(%s)\"" + r_iarg.default_argument + "\"";
-				r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+				if (r_iarg.default_argument.length() > 0) {
+					r_iarg.default_argument = "(%s)\"" + r_iarg.default_argument + "\"";
+					r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+				} else {
+					// No need for a special `in` statement to change `null` to `""`. Marshaling takes care of this already.
+					r_iarg.default_argument = "null";
+				}
 			} else {
 			} else {
 				CRASH_COND(r_iarg.type.cname != name_cache.type_String);
 				CRASH_COND(r_iarg.type.cname != name_cache.type_String);
 				r_iarg.default_argument = "\"" + r_iarg.default_argument + "\"";
 				r_iarg.default_argument = "\"" + r_iarg.default_argument + "\"";
@@ -3175,8 +3197,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
 			r_iarg.default_argument = "null";
 			r_iarg.default_argument = "null";
 			break;
 			break;
 		case Variant::DICTIONARY:
 		case Variant::DICTIONARY:
-			r_iarg.default_argument = "new %s()";
-			r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+			ERR_FAIL_COND_V_MSG(!p_val.operator Dictionary().is_empty(), false,
+					"Default value of type 'Dictionary' must be an empty dictionary.");
+			// The [cs_in] expression already interprets null values as empty dictionaries.
+			r_iarg.default_argument = "null";
+			r_iarg.def_param_mode = ArgumentInterface::CONSTANT;
 			break;
 			break;
 		case Variant::RID:
 		case Variant::RID:
 			ERR_FAIL_COND_V_MSG(r_iarg.type.cname != name_cache.type_RID, false,
 			ERR_FAIL_COND_V_MSG(r_iarg.type.cname != name_cache.type_RID, false,
@@ -3188,8 +3213,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
 			r_iarg.default_argument = "default";
 			r_iarg.default_argument = "default";
 			break;
 			break;
 		case Variant::ARRAY:
 		case Variant::ARRAY:
-			r_iarg.default_argument = "new %s { }";
-			r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+			ERR_FAIL_COND_V_MSG(!p_val.operator Array().is_empty(), false,
+					"Default value of type 'Array' must be an empty array.");
+			// The [cs_in] expression already interprets null values as empty arrays.
+			r_iarg.default_argument = "null";
+			r_iarg.def_param_mode = ArgumentInterface::CONSTANT;
 			break;
 			break;
 		case Variant::PACKED_BYTE_ARRAY:
 		case Variant::PACKED_BYTE_ARRAY:
 		case Variant::PACKED_INT32_ARRAY:
 		case Variant::PACKED_INT32_ARRAY:
@@ -3285,8 +3313,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 		itype = TypeInterface::create_value_type(String(#m_type)); \
 		itype = TypeInterface::create_value_type(String(#m_type)); \
 		itype.c_type_in = #m_type "*";                             \
 		itype.c_type_in = #m_type "*";                             \
 		itype.c_type_out = itype.cs_type;                          \
 		itype.c_type_out = itype.cs_type;                          \
-		itype.cs_in = "&%s";                                       \
-		itype.cs_in_is_unsafe = true;                              \
+		itype.cs_in_expr = "&%0";                                  \
+		itype.cs_in_expr_is_unsafe = true;                         \
 		builtin_types.insert(itype.cname, itype);                  \
 		builtin_types.insert(itype.cname, itype);                  \
 	}
 	}
 
 
@@ -3311,7 +3339,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 
 
 	// bool
 	// bool
 	itype = TypeInterface::create_value_type(String("bool"));
 	itype = TypeInterface::create_value_type(String("bool"));
-	itype.cs_in = "%s.ToGodotBool()";
+	itype.cs_in_expr = "%0.ToGodotBool()";
 	itype.cs_out = "%5return %0(%1).ToBool();";
 	itype.cs_out = "%5return %0(%1).ToBool();";
 	itype.c_type = "godot_bool";
 	itype.c_type = "godot_bool";
 	itype.c_type_in = itype.c_type;
 	itype.c_type_in = itype.c_type;
@@ -3411,15 +3439,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 	itype.cname = itype.name;
 	itype.cname = itype.name;
 	itype.proxy_name = "StringName";
 	itype.proxy_name = "StringName";
 	itype.cs_type = itype.proxy_name;
 	itype.cs_type = itype.proxy_name;
-	itype.cs_in = "ref %0.NativeValue";
+	itype.cs_in_expr = "(%1)(%0?.NativeValue ?? default)";
 	// Cannot pass null StringName to ptrcall
 	// Cannot pass null StringName to ptrcall
-	itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_string_name_new_copy(%1);\n";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
-	itype.c_arg_in = "&%s_in";
+	itype.c_arg_in = "&%s";
 	itype.c_type = "godot_string_name";
 	itype.c_type = "godot_string_name";
-	itype.c_type_in = "ref " + itype.c_type;
+	itype.c_type_in = itype.c_type;
 	itype.c_type_out = itype.cs_type;
 	itype.c_type_out = itype.cs_type;
-	itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringName(ref %1);\n";
+	itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringName(%1);\n";
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_ret_needs_default_initialization = true;
 	itype.c_ret_needs_default_initialization = true;
 	builtin_types.insert(itype.cname, itype);
 	builtin_types.insert(itype.cname, itype);
@@ -3430,13 +3457,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 	itype.cname = itype.name;
 	itype.cname = itype.name;
 	itype.proxy_name = "NodePath";
 	itype.proxy_name = "NodePath";
 	itype.cs_type = itype.proxy_name;
 	itype.cs_type = itype.proxy_name;
-	itype.cs_in = "ref %0.NativeValue";
+	itype.cs_in_expr = "(%1)(%0?.NativeValue ?? default)";
 	// Cannot pass null NodePath to ptrcall
 	// Cannot pass null NodePath to ptrcall
-	itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_node_path_new_copy(%1);\n";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
-	itype.c_arg_in = "&%s_in";
+	itype.c_arg_in = "&%s";
 	itype.c_type = "godot_node_path";
 	itype.c_type = "godot_node_path";
-	itype.c_type_in = "ref " + itype.c_type;
+	itype.c_type_in = itype.c_type;
 	itype.c_type_out = itype.cs_type;
 	itype.c_type_out = itype.cs_type;
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_ret_needs_default_initialization = true;
 	itype.c_ret_needs_default_initialization = true;
@@ -3461,7 +3487,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 	itype.proxy_name = "object";
 	itype.proxy_name = "object";
 	itype.cs_type = itype.proxy_name;
 	itype.cs_type = itype.proxy_name;
 	itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_VARIANT "(%1);\n";
 	itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_VARIANT "(%1);\n";
-	itype.c_out = "%5return " C_METHOD_MANAGED_FROM_VARIANT "(&%1);\n";
+	itype.c_out = "%5return " C_METHOD_MANAGED_FROM_VARIANT "(%1);\n";
 	itype.c_arg_in = "&%s_in";
 	itype.c_arg_in = "&%s_in";
 	itype.c_type = "godot_variant";
 	itype.c_type = "godot_variant";
 	itype.c_type_in = itype.cs_type;
 	itype.c_type_in = itype.cs_type;
@@ -3471,9 +3497,9 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 
 
 	// Callable
 	// Callable
 	itype = TypeInterface::create_value_type(String("Callable"));
 	itype = TypeInterface::create_value_type(String("Callable"));
-	itype.cs_in = "ref %s";
+	itype.cs_in_expr = "ref %0";
 	itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_CALLABLE "(ref %1);\n";
 	itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_CALLABLE "(ref %1);\n";
-	itype.c_out = "%5return " C_METHOD_MANAGED_FROM_CALLABLE "(&%1);\n";
+	itype.c_out = "%5return " C_METHOD_MANAGED_FROM_CALLABLE "(in %1);\n";
 	itype.c_arg_in = "&%s_in";
 	itype.c_arg_in = "&%s_in";
 	itype.c_type = "godot_callable";
 	itype.c_type = "godot_callable";
 	itype.c_type_in = "ref " + itype.cs_type;
 	itype.c_type_in = "ref " + itype.cs_type;
@@ -3487,7 +3513,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 	itype.cname = itype.name;
 	itype.cname = itype.name;
 	itype.proxy_name = "SignalInfo";
 	itype.proxy_name = "SignalInfo";
 	itype.cs_type = itype.proxy_name;
 	itype.cs_type = itype.proxy_name;
-	itype.cs_in = "ref %s";
+	itype.cs_in_expr = "ref %0";
 	itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(ref %1);\n";
 	itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(ref %1);\n";
 	itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(&%1);\n";
 	itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(&%1);\n";
 	itype.c_arg_in = "&%s_in";
 	itype.c_arg_in = "&%s_in";
@@ -3503,6 +3529,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 	itype.cname = itype.name;
 	itype.cname = itype.name;
 	itype.proxy_name = "object[]";
 	itype.proxy_name = "object[]";
 	itype.cs_type = "params object[]";
 	itype.cs_type = "params object[]";
+	itype.cs_in_expr = "%0 ?? Array.Empty<object>()";
 	// c_type, c_in and c_arg_in are hard-coded in the generator.
 	// c_type, c_in and c_arg_in are hard-coded in the generator.
 	// c_out and c_type_out are not applicable to VarArg.
 	// c_out and c_type_out are not applicable to VarArg.
 	itype.c_arg_in = "&%s_in";
 	itype.c_arg_in = "&%s_in";
@@ -3517,7 +3544,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 		itype.proxy_name = #m_proxy_t "[]";                                         \
 		itype.proxy_name = #m_proxy_t "[]";                                         \
 		itype.cs_type = itype.proxy_name;                                           \
 		itype.cs_type = itype.proxy_name;                                           \
 		itype.c_in = "%5using %0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \
 		itype.c_in = "%5using %0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \
-		itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(&%1);\n";       \
+		itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n";        \
 		itype.c_arg_in = "&%s_in";                                                  \
 		itype.c_arg_in = "&%s_in";                                                  \
 		itype.c_type = #m_managed_type;                                             \
 		itype.c_type = #m_managed_type;                                             \
 		itype.c_type_in = itype.proxy_name;                                         \
 		itype.c_type_in = itype.proxy_name;                                         \
@@ -3550,12 +3577,11 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 	itype.proxy_name = itype.name;
 	itype.proxy_name = itype.name;
 	itype.type_parameter_count = 1;
 	itype.type_parameter_count = 1;
 	itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
 	itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
-	itype.cs_in = "ref %0.NativeValue";
-	itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_array_new_copy(%1);\n";
+	itype.cs_in_expr = "(%1)(%0 ?? new()).NativeValue";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
-	itype.c_arg_in = "&%s_in";
+	itype.c_arg_in = "&%s";
 	itype.c_type = "godot_array";
 	itype.c_type = "godot_array";
-	itype.c_type_in = "ref " + itype.c_type;
+	itype.c_type_in = itype.c_type;
 	itype.c_type_out = itype.cs_type;
 	itype.c_type_out = itype.cs_type;
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_ret_needs_default_initialization = true;
 	itype.c_ret_needs_default_initialization = true;
@@ -3575,12 +3601,11 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 	itype.proxy_name = itype.name;
 	itype.proxy_name = itype.name;
 	itype.type_parameter_count = 2;
 	itype.type_parameter_count = 2;
 	itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
 	itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
-	itype.cs_in = "ref %0.NativeValue";
-	itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_dictionary_new_copy(%1);\n";
+	itype.cs_in_expr = "(%1)(%0 ?? new()).NativeValue";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
 	itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
-	itype.c_arg_in = "&%s_in";
+	itype.c_arg_in = "&%s";
 	itype.c_type = "godot_dictionary";
 	itype.c_type = "godot_dictionary";
-	itype.c_type_in = "ref " + itype.c_type;
+	itype.c_type_in = itype.c_type;
 	itype.c_type_out = itype.cs_type;
 	itype.c_type_out = itype.cs_type;
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
 	itype.c_ret_needs_default_initialization = true;
 	itype.c_ret_needs_default_initialization = true;

+ 18 - 5
modules/mono/editor/bindings_generator.h

@@ -265,9 +265,9 @@ class BindingsGenerator {
 		// --- C INTERFACE ---
 		// --- C INTERFACE ---
 
 
 		/**
 		/**
-		 * One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
+		 * One or more statements that transform the parameter before being passed as argument of a ptrcall.
 		 * If the statement adds a local that must be passed as the argument instead of the parameter,
 		 * If the statement adds a local that must be passed as the argument instead of the parameter,
-		 * the name of that local must be specified with [c_arg_in].
+		 * the expression with the name of that local must be specified with [c_arg_in].
 		 * Formatting elements:
 		 * Formatting elements:
 		 * %0: [c_type] of the parameter
 		 * %0: [c_type] of the parameter
 		 * %1: name of the parameter
 		 * %1: name of the parameter
@@ -277,7 +277,7 @@ class BindingsGenerator {
 		String c_in;
 		String c_in;
 
 
 		/**
 		/**
-		 * One or more statements that manipulate the parameter before being passed as argument of a vararg call.
+		 * One or more statements that transform the parameter before being passed as argument of a vararg call.
 		 * If the statement adds a local that must be passed as the argument instead of the parameter,
 		 * If the statement adds a local that must be passed as the argument instead of the parameter,
 		 * the name of that local must be specified with [c_arg_in].
 		 * the name of that local must be specified with [c_arg_in].
 		 * Formatting elements:
 		 * Formatting elements:
@@ -348,10 +348,23 @@ class BindingsGenerator {
 		 * An expression that overrides the way the parameter is passed to the internal call.
 		 * An expression that overrides the way the parameter is passed to the internal call.
 		 * If empty, the parameter is passed as is.
 		 * If empty, the parameter is passed as is.
 		 * Formatting elements:
 		 * Formatting elements:
-		 * %0 or %s: name of the parameter
+		 * %0: name of the parameter
+		 * %1: [c_type] of the parameter
+		 */
+		String cs_in_expr;
+		bool cs_in_expr_is_unsafe = false;
+
+		/**
+		 * One or more statements that transform the parameter before being passed to the internal call.
+		 * If the statement adds a local that must be passed as the argument instead of the parameter,
+		 * the expression with the name of that local must be specified with [cs_in_expr].
+		 * Formatting elements:
+		 * %0: [c_type] of the parameter
+		 * %1: name of the parameter
+		 * %2-4: reserved
+		 * %5: indentation text
 		 */
 		 */
 		String cs_in;
 		String cs_in;
-		bool cs_in_is_unsafe = false;
 
 
 		/**
 		/**
 		 * One or more statements that determine how a variable of this type is returned from a method.
 		 * One or more statements that determine how a variable of this type is returned from a method.

+ 8 - 0
modules/mono/glue/GodotSharp/.editorconfig

@@ -0,0 +1,8 @@
+[**/Generated/**.cs]
+# Validate parameter is non-null before using it
+# Useful for generated code, as it disables nullable
+dotnet_diagnostic.CA1062.severity = error
+# CA1069: Enums should not have duplicate values
+dotnet_diagnostic.CA1069.severity = none
+# CA1708: Identifiers should differ by more than case
+dotnet_diagnostic.CA1708.severity = none

+ 91 - 51
modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs

@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Collections;
 using System.Collections;
 using System.Diagnostics.CodeAnalysis;
 using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 
 
 namespace Godot.Collections
 namespace Godot.Collections
@@ -14,14 +15,14 @@ namespace Godot.Collections
     /// </summary>
     /// </summary>
     public sealed class Array : IList, IDisposable
     public sealed class Array : IList, IDisposable
     {
     {
-        public godot_array NativeValue;
+        internal godot_array.movable NativeValue;
 
 
         /// <summary>
         /// <summary>
         /// Constructs a new empty <see cref="Array"/>.
         /// Constructs a new empty <see cref="Array"/>.
         /// </summary>
         /// </summary>
         public Array()
         public Array()
         {
         {
-            NativeValue = NativeFuncs.godotsharp_array_new();
+            NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -32,7 +33,7 @@ namespace Godot.Collections
         public Array(IEnumerable collection) : this()
         public Array(IEnumerable collection) : this()
         {
         {
             if (collection == null)
             if (collection == null)
-                throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
+                throw new ArgumentNullException(nameof(collection));
 
 
             foreach (object element in collection)
             foreach (object element in collection)
                 Add(element);
                 Add(element);
@@ -47,9 +48,9 @@ namespace Godot.Collections
         public Array(params object[] array) : this()
         public Array(params object[] array) : this()
         {
         {
             if (array == null)
             if (array == null)
-                throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
+                throw new ArgumentNullException(nameof(array));
 
 
-            NativeValue = NativeFuncs.godotsharp_array_new();
+            NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
             int length = array.Length;
             int length = array.Length;
 
 
             Resize(length);
             Resize(length);
@@ -60,7 +61,9 @@ namespace Godot.Collections
 
 
         private Array(godot_array nativeValueToOwn)
         private Array(godot_array nativeValueToOwn)
         {
         {
-            NativeValue = nativeValueToOwn;
+            NativeValue = (godot_array.movable)(nativeValueToOwn.IsAllocated ?
+                nativeValueToOwn :
+                NativeFuncs.godotsharp_array_new());
         }
         }
 
 
         // Explicit name to make it very clear
         // Explicit name to make it very clear
@@ -84,7 +87,7 @@ namespace Godot.Collections
         public void Dispose(bool disposing)
         public void Dispose(bool disposing)
         {
         {
             // Always dispose `NativeValue` even if disposing is true
             // Always dispose `NativeValue` even if disposing is true
-            NativeValue.Dispose();
+            NativeValue.DangerousSelfRef.Dispose();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -95,7 +98,8 @@ namespace Godot.Collections
         public Array Duplicate(bool deep = false)
         public Array Duplicate(bool deep = false)
         {
         {
             godot_array newArray;
             godot_array newArray;
-            NativeFuncs.godotsharp_array_duplicate(ref NativeValue, deep.ToGodotBool(), out newArray);
+            var self = (godot_array)NativeValue;
+            NativeFuncs.godotsharp_array_duplicate(ref self, deep.ToGodotBool(), out newArray);
             return CreateTakingOwnershipOfDisposableValue(newArray);
             return CreateTakingOwnershipOfDisposableValue(newArray);
         }
         }
 
 
@@ -104,12 +108,20 @@ namespace Godot.Collections
         /// </summary>
         /// </summary>
         /// <param name="newSize">The new size of the array.</param>
         /// <param name="newSize">The new size of the array.</param>
         /// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
         /// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
-        public Error Resize(int newSize) => NativeFuncs.godotsharp_array_resize(ref NativeValue, newSize);
+        public Error Resize(int newSize)
+        {
+            var self = (godot_array)NativeValue;
+            return NativeFuncs.godotsharp_array_resize(ref self, newSize);
+        }
 
 
         /// <summary>
         /// <summary>
         /// Shuffles the contents of this <see cref="Array"/> into a random order.
         /// Shuffles the contents of this <see cref="Array"/> into a random order.
         /// </summary>
         /// </summary>
-        public void Shuffle() => NativeFuncs.godotsharp_array_shuffle(ref NativeValue);
+        public void Shuffle()
+        {
+            var self = (godot_array)NativeValue;
+            NativeFuncs.godotsharp_array_shuffle(ref self);
+        }
 
 
         /// <summary>
         /// <summary>
         /// Concatenates these two <see cref="Array"/>s.
         /// Concatenates these two <see cref="Array"/>s.
@@ -119,6 +131,17 @@ namespace Godot.Collections
         /// <returns>A new Godot Array with the contents of both arrays.</returns>
         /// <returns>A new Godot Array with the contents of both arrays.</returns>
         public static Array operator +(Array left, Array right)
         public static Array operator +(Array left, Array right)
         {
         {
+            if (left == null)
+            {
+                if (right == null)
+                    return new Array();
+
+                return right.Duplicate(deep: false);
+            }
+
+            if (right == null)
+                return left.Duplicate(deep: false);
+
             int leftCount = left.Count;
             int leftCount = left.Count;
             int rightCount = right.Count;
             int rightCount = right.Count;
 
 
@@ -146,14 +169,15 @@ namespace Godot.Collections
             get
             get
             {
             {
                 GetVariantBorrowElementAt(index, out godot_variant borrowElem);
                 GetVariantBorrowElementAt(index, out godot_variant borrowElem);
-                return Marshaling.variant_to_mono_object(&borrowElem);
+                return Marshaling.ConvertVariantToManagedObject(borrowElem);
             }
             }
             set
             set
             {
             {
                 if (index < 0 || index >= Count)
                 if (index < 0 || index >= Count)
-                    throw new IndexOutOfRangeException();
-                godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref NativeValue);
-                ptrw[index] = Marshaling.mono_object_to_variant(value);
+                    throw new ArgumentOutOfRangeException(nameof(index));
+                var self = (godot_array)NativeValue;
+                godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref self);
+                ptrw[index] = Marshaling.ConvertManagedObjectToVariant(value);
             }
             }
         }
         }
 
 
@@ -163,10 +187,11 @@ namespace Godot.Collections
         /// </summary>
         /// </summary>
         /// <param name="value">The object to add.</param>
         /// <param name="value">The object to add.</param>
         /// <returns>The new size after adding the object.</returns>
         /// <returns>The new size after adding the object.</returns>
-        public unsafe int Add(object value)
+        public int Add(object value)
         {
         {
-            using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
-            return NativeFuncs.godotsharp_array_add(ref NativeValue, &variantValue);
+            using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+            var self = (godot_array)NativeValue;
+            return NativeFuncs.godotsharp_array_add(ref self, variantValue);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -187,10 +212,11 @@ namespace Godot.Collections
         /// </summary>
         /// </summary>
         /// <param name="value">The object to search for.</param>
         /// <param name="value">The object to search for.</param>
         /// <returns>The index of the object, or -1 if not found.</returns>
         /// <returns>The index of the object, or -1 if not found.</returns>
-        public unsafe int IndexOf(object value)
+        public int IndexOf(object value)
         {
         {
-            using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
-            return NativeFuncs.godotsharp_array_index_of(ref NativeValue, &variantValue);
+            using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+            var self = (godot_array)NativeValue;
+            return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -201,13 +227,14 @@ namespace Godot.Collections
         /// </summary>
         /// </summary>
         /// <param name="index">The index to insert at.</param>
         /// <param name="index">The index to insert at.</param>
         /// <param name="value">The object to insert.</param>
         /// <param name="value">The object to insert.</param>
-        public unsafe void Insert(int index, object value)
+        public void Insert(int index, object value)
         {
         {
             if (index < 0 || index > Count)
             if (index < 0 || index > Count)
-                throw new IndexOutOfRangeException();
+                throw new ArgumentOutOfRangeException(nameof(index));
 
 
-            using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
-            NativeFuncs.godotsharp_array_insert(ref NativeValue, index, &variantValue);
+            using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+            var self = (godot_array)NativeValue;
+            NativeFuncs.godotsharp_array_insert(ref self, index, variantValue);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -229,9 +256,10 @@ namespace Godot.Collections
         public void RemoveAt(int index)
         public void RemoveAt(int index)
         {
         {
             if (index < 0 || index > Count)
             if (index < 0 || index > Count)
-                throw new IndexOutOfRangeException();
+                throw new ArgumentOutOfRangeException(nameof(index));
 
 
-            NativeFuncs.godotsharp_array_remove_at(ref NativeValue, index);
+            var self = (godot_array)NativeValue;
+            NativeFuncs.godotsharp_array_remove_at(ref self, index);
         }
         }
 
 
         // ICollection
         // ICollection
@@ -241,7 +269,7 @@ namespace Godot.Collections
         /// This is also known as the size or length of the array.
         /// This is also known as the size or length of the array.
         /// </summary>
         /// </summary>
         /// <returns>The number of elements.</returns>
         /// <returns>The number of elements.</returns>
-        public int Count => NativeValue.Size;
+        public int Count => NativeValue.DangerousSelfRef.Size;
 
 
         object ICollection.SyncRoot => this;
         object ICollection.SyncRoot => this;
 
 
@@ -252,21 +280,21 @@ namespace Godot.Collections
         /// untyped C# array, starting at the given index.
         /// untyped C# array, starting at the given index.
         /// </summary>
         /// </summary>
         /// <param name="array">The array to copy to.</param>
         /// <param name="array">The array to copy to.</param>
-        /// <param name="destIndex">The index to start at.</param>
-        public void CopyTo(System.Array array, int destIndex)
+        /// <param name="index">The index to start at.</param>
+        public void CopyTo(System.Array array, int index)
         {
         {
             if (array == null)
             if (array == null)
                 throw new ArgumentNullException(nameof(array), "Value cannot be null.");
                 throw new ArgumentNullException(nameof(array), "Value cannot be null.");
 
 
-            if (destIndex < 0)
+            if (index < 0)
             {
             {
-                throw new ArgumentOutOfRangeException(nameof(destIndex),
+                throw new ArgumentOutOfRangeException(nameof(index),
                     "Number was less than the array's lower bound in the first dimension.");
                     "Number was less than the array's lower bound in the first dimension.");
             }
             }
 
 
             int count = Count;
             int count = Count;
 
 
-            if (array.Length < (destIndex + count))
+            if (array.Length < (index + count))
             {
             {
                 throw new ArgumentException(
                 throw new ArgumentException(
                     "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
                     "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
@@ -276,9 +304,9 @@ namespace Godot.Collections
             {
             {
                 for (int i = 0; i < count; i++)
                 for (int i = 0; i < count; i++)
                 {
                 {
-                    object obj = Marshaling.variant_to_mono_object(&(*NativeValue._p)._arrayVector._ptr[i]);
-                    array.SetValue(obj, destIndex);
-                    destIndex++;
+                    object obj = Marshaling.ConvertVariantToManagedObject(NativeValue.DangerousSelfRef.Elements[i]);
+                    array.SetValue(obj, index);
+                    index++;
                 }
                 }
             }
             }
         }
         }
@@ -303,11 +331,12 @@ namespace Godot.Collections
         /// Converts this <see cref="Array"/> to a string.
         /// Converts this <see cref="Array"/> to a string.
         /// </summary>
         /// </summary>
         /// <returns>A string representation of this array.</returns>
         /// <returns>A string representation of this array.</returns>
-        public override unsafe string ToString()
+        public override string ToString()
         {
         {
-            using godot_string str = default;
-            NativeFuncs.godotsharp_array_to_string(ref NativeValue, &str);
-            return Marshaling.mono_string_from_godot(str);
+            var self = (godot_array)NativeValue;
+            NativeFuncs.godotsharp_array_to_string(ref self, out godot_string str);
+            using (str)
+                return Marshaling.ConvertStringToManaged(str);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -316,7 +345,7 @@ namespace Godot.Collections
         internal void GetVariantBorrowElementAt(int index, out godot_variant elem)
         internal void GetVariantBorrowElementAt(int index, out godot_variant elem)
         {
         {
             if (index < 0 || index >= Count)
             if (index < 0 || index >= Count)
-                throw new IndexOutOfRangeException();
+                throw new ArgumentOutOfRangeException(nameof(index));
             GetVariantBorrowElementAtUnchecked(index, out elem);
             GetVariantBorrowElementAtUnchecked(index, out elem);
         }
         }
 
 
@@ -325,7 +354,7 @@ namespace Godot.Collections
         /// </summary>
         /// </summary>
         internal unsafe void GetVariantBorrowElementAtUnchecked(int index, out godot_variant elem)
         internal unsafe void GetVariantBorrowElementAtUnchecked(int index, out godot_variant elem)
         {
         {
-            elem = (*NativeValue._p)._arrayVector._ptr[index];
+            elem = NativeValue.DangerousSelfRef.Elements[index];
         }
         }
     }
     }
 
 
@@ -344,11 +373,16 @@ namespace Godot.Collections
     /// </summary>
     /// </summary>
     /// <typeparam name="T">The type of the array.</typeparam>
     /// <typeparam name="T">The type of the array.</typeparam>
     [SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
     [SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
+    [SuppressMessage("Naming", "CA1710", MessageId = "Identifiers should have correct suffix")]
     public sealed class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>, IGenericGodotArray
     public sealed class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>, IGenericGodotArray
     {
     {
         private readonly Array _underlyingArray;
         private readonly Array _underlyingArray;
 
 
-        internal ref godot_array NativeValue => ref _underlyingArray.NativeValue;
+        internal ref godot_array.movable NativeValue
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => ref _underlyingArray.NativeValue;
+        }
 
 
         // ReSharper disable StaticMemberInGenericType
         // ReSharper disable StaticMemberInGenericType
         // Warning is about unique static fields being created for each generic type combination:
         // Warning is about unique static fields being created for each generic type combination:
@@ -376,7 +410,7 @@ namespace Godot.Collections
         public Array(IEnumerable<T> collection)
         public Array(IEnumerable<T> collection)
         {
         {
             if (collection == null)
             if (collection == null)
-                throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
+                throw new ArgumentNullException(nameof(collection));
 
 
             _underlyingArray = new Array(collection);
             _underlyingArray = new Array(collection);
         }
         }
@@ -389,9 +423,7 @@ namespace Godot.Collections
         public Array(params T[] array) : this()
         public Array(params T[] array) : this()
         {
         {
             if (array == null)
             if (array == null)
-            {
-                throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
-            }
+                throw new ArgumentNullException(nameof(array));
 
 
             _underlyingArray = new Array(array);
             _underlyingArray = new Array(array);
         }
         }
@@ -415,7 +447,7 @@ namespace Godot.Collections
         /// <param name="from">The typed array to convert.</param>
         /// <param name="from">The typed array to convert.</param>
         public static explicit operator Array(Array<T> from)
         public static explicit operator Array(Array<T> from)
         {
         {
-            return from._underlyingArray;
+            return from?._underlyingArray;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -454,6 +486,17 @@ namespace Godot.Collections
         /// <returns>A new Godot Array with the contents of both arrays.</returns>
         /// <returns>A new Godot Array with the contents of both arrays.</returns>
         public static Array<T> operator +(Array<T> left, Array<T> right)
         public static Array<T> operator +(Array<T> left, Array<T> right)
         {
         {
+            if (left == null)
+            {
+                if (right == null)
+                    return new Array<T>();
+
+                return right.Duplicate(deep: false);
+            }
+
+            if (right == null)
+                return left.Duplicate(deep: false);
+
             return new Array<T>(left._underlyingArray + right._underlyingArray);
             return new Array<T>(left._underlyingArray + right._underlyingArray);
         }
         }
 
 
@@ -468,10 +511,7 @@ namespace Godot.Collections
             get
             get
             {
             {
                 _underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem);
                 _underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem);
-                unsafe
-                {
-                    return (T)Marshaling.variant_to_mono_object_of_type(&borrowElem, TypeOfElements);
-                }
+                return (T)Marshaling.ConvertVariantToManagedObjectOfType(borrowElem, TypeOfElements);
             }
             }
             set => _underlyingArray[index] = value;
             set => _underlyingArray[index] = value;
         }
         }

+ 4 - 4
modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs

@@ -167,7 +167,7 @@ namespace Godot
                     case 2:
                     case 2:
                         return Column2;
                         return Column2;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(column));
                 }
                 }
             }
             }
             set
             set
@@ -184,7 +184,7 @@ namespace Godot
                         Column2 = value;
                         Column2 = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(column));
                 }
                 }
             }
             }
         }
         }
@@ -386,7 +386,7 @@ namespace Godot
                 case 2:
                 case 2:
                     return Row2;
                     return Row2;
                 default:
                 default:
-                    throw new IndexOutOfRangeException();
+                    throw new ArgumentOutOfRangeException(nameof(index));
             }
             }
         }
         }
 
 
@@ -413,7 +413,7 @@ namespace Godot
                     Row2 = value;
                     Row2 = value;
                     return;
                     return;
                 default:
                 default:
-                    throw new IndexOutOfRangeException();
+                    throw new ArgumentOutOfRangeException(nameof(index));
             }
             }
         }
         }
 
 

+ 18 - 13
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs

@@ -18,22 +18,24 @@ namespace Godot.Bridge
                 if (godotObject == null)
                 if (godotObject == null)
                 {
                 {
                     *ret = default;
                     *ret = default;
-                    (*refCallError).error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL;
+                    (*refCallError).Error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL;
                     return false.ToGodotBool();
                     return false.ToGodotBool();
                 }
                 }
 
 
-                using godot_string dest = default;
-                NativeFuncs.godotsharp_string_name_as_string(&dest, method);
-                string methodStr = Marshaling.mono_string_from_godot(dest);
+                NativeFuncs.godotsharp_string_name_as_string(out godot_string dest, CustomUnsafe.AsRef(method));
+                string methodStr;
+                using (dest)
+                    methodStr = Marshaling.ConvertStringToManaged(dest);
 
 
-                bool methodInvoked = godotObject.InternalGodotScriptCall(methodStr, args, argCount, out godot_variant retValue);
+                bool methodInvoked = godotObject.InternalGodotScriptCall(methodStr, new NativeVariantPtrArgs(args),
+                    argCount, out godot_variant retValue);
 
 
                 if (!methodInvoked)
                 if (!methodInvoked)
                 {
                 {
                     *ret = default;
                     *ret = default;
                     // This is important, as it tells Object::call that no method was called.
                     // This is important, as it tells Object::call that no method was called.
                     // Otherwise, it would prevent Object::call from calling native methods.
                     // Otherwise, it would prevent Object::call from calling native methods.
-                    (*refCallError).error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD;
+                    (*refCallError).Error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD;
                     return false.ToGodotBool();
                     return false.ToGodotBool();
                 }
                 }
 
 
@@ -60,12 +62,15 @@ namespace Godot.Bridge
                     throw new InvalidOperationException();
                     throw new InvalidOperationException();
 
 
                 var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
                 var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
-                    NativeFuncs.godotsharp_string_name_new_copy(name));
+                    NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(name)));
 
 
-                if (godotObject.InternalGodotScriptSetFieldOrPropViaReflection(nameManaged.ToString(), value))
+                if (godotObject.InternalGodotScriptSetFieldOrPropViaReflection(
+                        nameManaged.ToString(), CustomUnsafe.AsRef(value)))
+                {
                     return true.ToGodotBool();
                     return true.ToGodotBool();
+                }
 
 
-                object valueManaged = Marshaling.variant_to_mono_object(value);
+                object valueManaged = Marshaling.ConvertVariantToManagedObject(CustomUnsafe.AsRef(value));
 
 
                 return godotObject._Set(nameManaged, valueManaged).ToGodotBool();
                 return godotObject._Set(nameManaged, valueManaged).ToGodotBool();
             }
             }
@@ -89,10 +94,10 @@ namespace Godot.Bridge
                     throw new InvalidOperationException();
                     throw new InvalidOperationException();
 
 
                 var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
                 var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
-                    NativeFuncs.godotsharp_string_name_new_copy(name));
+                    NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(name)));
 
 
                 if (godotObject.InternalGodotScriptGetFieldOrPropViaReflection(nameManaged.ToString(),
                 if (godotObject.InternalGodotScriptGetFieldOrPropViaReflection(nameManaged.ToString(),
-                    out godot_variant outRetValue))
+                        out godot_variant outRetValue))
                 {
                 {
                     *outRet = outRetValue;
                     *outRet = outRetValue;
                     return true.ToGodotBool();
                     return true.ToGodotBool();
@@ -106,7 +111,7 @@ namespace Godot.Bridge
                     return false.ToGodotBool();
                     return false.ToGodotBool();
                 }
                 }
 
 
-                *outRet = Marshaling.mono_object_to_variant(ret);
+                *outRet = Marshaling.ConvertManagedObjectToVariant(ret);
                 return true.ToGodotBool();
                 return true.ToGodotBool();
             }
             }
             catch (Exception e)
             catch (Exception e)
@@ -158,7 +163,7 @@ namespace Godot.Bridge
                     return;
                     return;
                 }
                 }
 
 
-                *outRes = Marshaling.mono_string_to_godot(resultStr);
+                *outRes = Marshaling.ConvertStringToNative(resultStr);
                 *outValid = true.ToGodotBool();
                 *outValid = true.ToGodotBool();
             }
             }
             catch (Exception e)
             catch (Exception e)

+ 22 - 19
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs

@@ -104,8 +104,8 @@ namespace Godot.Bridge
 
 
                 for (int i = 0; i < paramCount; i++)
                 for (int i = 0; i < paramCount; i++)
                 {
                 {
-                    invokeParams[i] = Marshaling.variant_to_mono_object_of_type(
-                        args[i], parameters[i].ParameterType);
+                    invokeParams[i] = Marshaling.ConvertVariantToManagedObjectOfType(
+                        *args[i], parameters[i].ParameterType);
                 }
                 }
 
 
                 ctor.Invoke(obj, invokeParams);
                 ctor.Invoke(obj, invokeParams);
@@ -149,7 +149,7 @@ namespace Godot.Bridge
                     return;
                     return;
                 }
                 }
 
 
-                *outRes = NativeFuncs.godotsharp_string_name_new_copy(nativeName.NativeValue);
+                *outRes = NativeFuncs.godotsharp_string_name_new_copy((godot_string_name)nativeName.NativeValue);
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
@@ -177,7 +177,7 @@ namespace Godot.Bridge
         {
         {
             // Performance is not critical here as this will be replaced with a generated dictionary.
             // Performance is not critical here as this will be replaced with a generated dictionary.
             using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
             using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
-                NativeFuncs.godotsharp_string_name_new_copy(nativeTypeName));
+                NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName)));
             string nativeTypeNameStr = stringName.ToString();
             string nativeTypeNameStr = stringName.ToString();
 
 
             if (nativeTypeNameStr[0] == '_')
             if (nativeTypeNameStr[0] == '_')
@@ -277,7 +277,8 @@ namespace Godot.Bridge
 
 
                 *outOwnerIsNull = false.ToGodotBool();
                 *outOwnerIsNull = false.ToGodotBool();
 
 
-                owner.InternalRaiseEventSignal(eventSignalName, args, argCount);
+                owner.InternalRaiseEventSignal(CustomUnsafe.AsRef(eventSignalName),
+                    new NativeVariantPtrArgs(args), argCount);
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
@@ -302,9 +303,10 @@ namespace Godot.Bridge
                     // Legacy signals
                     // Legacy signals
 
 
                     foreach (var signalDelegate in top
                     foreach (var signalDelegate in top
-                        .GetNestedTypes(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public)
-                        .Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
-                        .Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any()))
+                                 .GetNestedTypes(BindingFlags.DeclaredOnly | BindingFlags.NonPublic |
+                                                 BindingFlags.Public)
+                                 .Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
+                                 .Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any()))
                     {
                     {
                         var invokeMethod = signalDelegate.GetMethod("Invoke");
                         var invokeMethod = signalDelegate.GetMethod("Invoke");
 
 
@@ -315,7 +317,7 @@ namespace Godot.Bridge
 
 
                         foreach (var parameters in invokeMethod.GetParameters())
                         foreach (var parameters in invokeMethod.GetParameters())
                         {
                         {
-                            var paramType = Marshaling.managed_to_variant_type(
+                            var paramType = Marshaling.ConvertManagedTypeToVariantType(
                                 parameters.ParameterType, out bool nilIsVariant);
                                 parameters.ParameterType, out bool nilIsVariant);
                             signalParams.Add(new Dictionary()
                             signalParams.Add(new Dictionary()
                             {
                             {
@@ -341,8 +343,8 @@ namespace Godot.Bridge
                         BindingFlags.NonPublic | BindingFlags.Public);
                         BindingFlags.NonPublic | BindingFlags.Public);
 
 
                     foreach (var eventSignalField in fields
                     foreach (var eventSignalField in fields
-                        .Where(f => typeof(Delegate).IsAssignableFrom(f.FieldType))
-                        .Where(f => foundEventSignals.Contains(f.Name)))
+                                 .Where(f => typeof(Delegate).IsAssignableFrom(f.FieldType))
+                                 .Where(f => foundEventSignals.Contains(f.Name)))
                     {
                     {
                         var delegateType = eventSignalField.FieldType;
                         var delegateType = eventSignalField.FieldType;
                         var invokeMethod = delegateType.GetMethod("Invoke");
                         var invokeMethod = delegateType.GetMethod("Invoke");
@@ -354,7 +356,7 @@ namespace Godot.Bridge
 
 
                         foreach (var parameters in invokeMethod.GetParameters())
                         foreach (var parameters in invokeMethod.GetParameters())
                         {
                         {
-                            var paramType = Marshaling.managed_to_variant_type(
+                            var paramType = Marshaling.ConvertManagedTypeToVariantType(
                                 parameters.ParameterType, out bool nilIsVariant);
                                 parameters.ParameterType, out bool nilIsVariant);
                             signalParams.Add(new Dictionary()
                             signalParams.Add(new Dictionary()
                             {
                             {
@@ -370,7 +372,7 @@ namespace Godot.Bridge
                     top = top.BaseType;
                     top = top.BaseType;
                 }
                 }
 
 
-                *outRetSignals = NativeFuncs.godotsharp_dictionary_new_copy(signals.NativeValue);
+                *outRetSignals = NativeFuncs.godotsharp_dictionary_new_copy((godot_dictionary)signals.NativeValue);
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
@@ -387,7 +389,7 @@ namespace Godot.Bridge
                 // Performance is not critical here as this will be replaced with source generators.
                 // Performance is not critical here as this will be replaced with source generators.
                 using var signals = new Dictionary();
                 using var signals = new Dictionary();
 
 
-                string signalNameStr = Marshaling.mono_string_from_godot(*signalName);
+                string signalNameStr = Marshaling.ConvertStringToManaged(*signalName);
 
 
                 Type top = _scriptBridgeMap[scriptPtr];
                 Type top = _scriptBridgeMap[scriptPtr];
                 Type native = Object.InternalGetClassNativeBase(top);
                 Type native = Object.InternalGetClassNativeBase(top);
@@ -401,7 +403,7 @@ namespace Godot.Bridge
                         .Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
                         .Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
                         .Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any())
                         .Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any())
                         .Any(signalDelegate => signalDelegate.Name == signalNameStr)
                         .Any(signalDelegate => signalDelegate.Name == signalNameStr)
-                    )
+                       )
                     {
                     {
                         return true.ToGodotBool();
                         return true.ToGodotBool();
                     }
                     }
@@ -413,7 +415,7 @@ namespace Godot.Bridge
                             BindingFlags.NonPublic | BindingFlags.Public)
                             BindingFlags.NonPublic | BindingFlags.Public)
                         .Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
                         .Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
                         .Any(eventSignal => eventSignal.Name == signalNameStr)
                         .Any(eventSignal => eventSignal.Name == signalNameStr)
-                    )
+                       )
                     {
                     {
                         return true.ToGodotBool();
                         return true.ToGodotBool();
                     }
                     }
@@ -440,7 +442,7 @@ namespace Godot.Bridge
                 if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
                 if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
                     return false.ToGodotBool();
                     return false.ToGodotBool();
 
 
-                string methodStr = Marshaling.mono_string_from_godot(*method);
+                string methodStr = Marshaling.ConvertStringToManaged(*method);
 
 
                 if (deep.ToBool())
                 if (deep.ToBool())
                 {
                 {
@@ -517,7 +519,7 @@ namespace Godot.Bridge
         {
         {
             try
             try
             {
             {
-                string scriptPathStr = Marshaling.mono_string_from_godot(*scriptPath);
+                string scriptPathStr = Marshaling.ConvertStringToManaged(*scriptPath);
 
 
                 if (!_scriptLookupMap.TryGetValue(scriptPathStr, out var lookupInfo))
                 if (!_scriptLookupMap.TryGetValue(scriptPathStr, out var lookupInfo))
                     return false.ToGodotBool();
                     return false.ToGodotBool();
@@ -612,7 +614,8 @@ namespace Godot.Bridge
                 }
                 }
 
 
                 *outRpcFunctionsDest =
                 *outRpcFunctionsDest =
-                    NativeFuncs.godotsharp_dictionary_new_copy(((Dictionary)rpcFunctions).NativeValue);
+                    NativeFuncs.godotsharp_dictionary_new_copy(
+                        (godot_dictionary)((Dictionary)rpcFunctions).NativeValue);
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {

+ 61 - 5
modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs

@@ -1,5 +1,7 @@
 using System;
 using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Godot.NativeInterop;
 
 
 namespace Godot
 namespace Godot
 {
 {
@@ -24,7 +26,7 @@ namespace Godot
     /// }
     /// }
     /// </code>
     /// </code>
     /// </example>
     /// </example>
-    public struct Callable
+    public readonly struct Callable
     {
     {
         private readonly Object _target;
         private readonly Object _target;
         private readonly StringName _method;
         private readonly StringName _method;
@@ -34,10 +36,12 @@ namespace Godot
         /// Object that contains the method.
         /// Object that contains the method.
         /// </summary>
         /// </summary>
         public Object Target => _target;
         public Object Target => _target;
+
         /// <summary>
         /// <summary>
         /// Name of the method that will be called.
         /// Name of the method that will be called.
         /// </summary>
         /// </summary>
         public StringName Method => _method;
         public StringName Method => _method;
+
         /// <summary>
         /// <summary>
         /// Delegate of the method that will be called.
         /// Delegate of the method that will be called.
         /// </summary>
         /// </summary>
@@ -73,15 +77,43 @@ namespace Godot
             _delegate = @delegate;
             _delegate = @delegate;
         }
         }
 
 
+        private const int VarArgsSpanThreshold = 5;
+
         /// <summary>
         /// <summary>
         /// Calls the method represented by this <see cref="Callable"/>.
         /// Calls the method represented by this <see cref="Callable"/>.
         /// Arguments can be passed and should match the method's signature.
         /// Arguments can be passed and should match the method's signature.
         /// </summary>
         /// </summary>
         /// <param name="args">Arguments that will be passed to the method call.</param>
         /// <param name="args">Arguments that will be passed to the method call.</param>
         /// <returns>The value returned by the method.</returns>
         /// <returns>The value returned by the method.</returns>
-        public object Call(params object[] args)
+        public unsafe object Call(params object[] args)
         {
         {
-            return godot_icall_Callable_Call(ref this, args);
+            using godot_callable callable = Marshaling.ConvertCallableToNative(this);
+
+            int argc = args.Length;
+
+            Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
+                stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
+                new godot_variant.movable[argc];
+
+            Span<IntPtr> argsSpan = argc <= 10 ?
+                stackalloc IntPtr[argc] :
+                new IntPtr[argc];
+
+            using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
+
+            fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
+            fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
+            {
+                for (int i = 0; i < argc; i++)
+                {
+                    varargs[i] = Marshaling.ConvertManagedObjectToVariant(args[i]);
+                    argsPtr[i] = new IntPtr(&varargs[i]);
+                }
+
+                using godot_variant ret = NativeFuncs.godotsharp_callable_call(callable,
+                    (godot_variant**)argsPtr, argc, out _);
+                return Marshaling.ConvertVariantToManagedObject(ret);
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -89,9 +121,33 @@ namespace Godot
         /// Arguments can be passed and should match the method's signature.
         /// Arguments can be passed and should match the method's signature.
         /// </summary>
         /// </summary>
         /// <param name="args">Arguments that will be passed to the method call.</param>
         /// <param name="args">Arguments that will be passed to the method call.</param>
-        public void CallDeferred(params object[] args)
+        public unsafe void CallDeferred(params object[] args)
         {
         {
-            godot_icall_Callable_CallDeferred(ref this, args);
+            using godot_callable callable = Marshaling.ConvertCallableToNative(this);
+
+            int argc = args.Length;
+
+            Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
+                stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
+                new godot_variant.movable[argc];
+
+            Span<IntPtr> argsSpan = argc <= 10 ?
+                stackalloc IntPtr[argc] :
+                new IntPtr[argc];
+
+            using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
+
+            fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
+            fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
+            {
+                for (int i = 0; i < argc; i++)
+                {
+                    varargs[i] = Marshaling.ConvertManagedObjectToVariant(args[i]);
+                    argsPtr[i] = new IntPtr(&varargs[i]);
+                }
+
+                NativeFuncs.godotsharp_callable_call_deferred(callable, (godot_variant**)argsPtr, argc);
+            }
         }
         }
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]

+ 4 - 4
modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs

@@ -210,7 +210,7 @@ namespace Godot
                     case 3:
                     case 3:
                         return a;
                         return a;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
             set
             set
@@ -230,7 +230,7 @@ namespace Godot
                         a = value;
                         a = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
         }
         }
@@ -841,7 +841,7 @@ namespace Godot
             return ParseCol4(str, ofs) * 16 + ParseCol4(str, ofs + 1);
             return ParseCol4(str, ofs) * 16 + ParseCol4(str, ofs + 1);
         }
         }
 
 
-        private string ToHex32(float val)
+        private static string ToHex32(float val)
         {
         {
             byte b = (byte)Mathf.RoundToInt(Mathf.Clamp(val * 255, 0, 255));
             byte b = (byte)Mathf.RoundToInt(Mathf.Clamp(val * 255, 0, 255));
             return b.HexEncode();
             return b.HexEncode();
@@ -849,7 +849,7 @@ namespace Godot
 
 
         internal static bool HtmlIsValid(string color)
         internal static bool HtmlIsValid(string color)
         {
         {
-            if (color.Length == 0)
+            if (string.IsNullOrEmpty(color))
             {
             {
                 return false;
                 return false;
             }
             }

+ 7 - 7
modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs

@@ -18,7 +18,7 @@ namespace Godot
             else
             else
                 sb.Append(type);
                 sb.Append(type);
 
 
-            sb.Append(" ");
+            sb.Append(' ');
         }
         }
 
 
         [UnmanagedCallersOnly]
         [UnmanagedCallersOnly]
@@ -55,15 +55,15 @@ namespace Godot
             if (methodBase is MethodInfo)
             if (methodBase is MethodInfo)
                 sb.AppendTypeName(((MethodInfo)methodBase).ReturnType);
                 sb.AppendTypeName(((MethodInfo)methodBase).ReturnType);
 
 
-            sb.Append(methodBase.DeclaringType.FullName);
-            sb.Append(".");
+            sb.Append(methodBase.DeclaringType?.FullName ?? "<unknown>");
+            sb.Append('.');
             sb.Append(methodBase.Name);
             sb.Append(methodBase.Name);
 
 
             if (methodBase.IsGenericMethod)
             if (methodBase.IsGenericMethod)
             {
             {
                 Type[] genericParams = methodBase.GetGenericArguments();
                 Type[] genericParams = methodBase.GetGenericArguments();
 
 
-                sb.Append("<");
+                sb.Append('<');
 
 
                 for (int j = 0; j < genericParams.Length; j++)
                 for (int j = 0; j < genericParams.Length; j++)
                 {
                 {
@@ -73,10 +73,10 @@ namespace Godot
                     sb.AppendTypeName(genericParams[j]);
                     sb.AppendTypeName(genericParams[j]);
                 }
                 }
 
 
-                sb.Append(">");
+                sb.Append('>');
             }
             }
 
 
-            sb.Append("(");
+            sb.Append('(');
 
 
             bool varArgs = (methodBase.CallingConvention & CallingConventions.VarArgs) != 0;
             bool varArgs = (methodBase.CallingConvention & CallingConventions.VarArgs) != 0;
 
 
@@ -93,7 +93,7 @@ namespace Godot
                 sb.AppendTypeName(parameter[i].ParameterType);
                 sb.AppendTypeName(parameter[i].ParameterType);
             }
             }
 
 
-            sb.Append(")");
+            sb.Append(')');
 
 
             methodDecl = sb.ToString();
             methodDecl = sb.ToString();
         }
         }

+ 3 - 3
modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs

@@ -48,13 +48,13 @@ namespace Godot
 
 
                 for (uint i = 0; i < argc; i++)
                 for (uint i = 0; i < argc; i++)
                 {
                 {
-                    managedArgs[i] = Marshaling.variant_to_mono_object_of_type(
-                        args[i], parameterInfos[i].ParameterType);
+                    managedArgs[i] = Marshaling.ConvertVariantToManagedObjectOfType(
+                        *args[i], parameterInfos[i].ParameterType);
                 }
                 }
 
 
                 object invokeRet = @delegate.DynamicInvoke(managedArgs);
                 object invokeRet = @delegate.DynamicInvoke(managedArgs);
 
 
-                *outRet = Marshaling.mono_object_to_variant(invokeRet);
+                *outRet = Marshaling.ConvertManagedObjectToVariant(invokeRet);
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {

+ 121 - 84
modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Collections;
 using System.Collections;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 using System.Diagnostics.CodeAnalysis;
 using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
 
 
 namespace Godot.Collections
 namespace Godot.Collections
 {
 {
@@ -15,14 +16,14 @@ namespace Godot.Collections
         IDictionary,
         IDictionary,
         IDisposable
         IDisposable
     {
     {
-        public godot_dictionary NativeValue;
+        internal godot_dictionary.movable NativeValue;
 
 
         /// <summary>
         /// <summary>
         /// Constructs a new empty <see cref="Dictionary"/>.
         /// Constructs a new empty <see cref="Dictionary"/>.
         /// </summary>
         /// </summary>
         public Dictionary()
         public Dictionary()
         {
         {
-            NativeValue = NativeFuncs.godotsharp_dictionary_new();
+            NativeValue = (godot_dictionary.movable)NativeFuncs.godotsharp_dictionary_new();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -33,7 +34,7 @@ namespace Godot.Collections
         public Dictionary(IDictionary dictionary) : this()
         public Dictionary(IDictionary dictionary) : this()
         {
         {
             if (dictionary == null)
             if (dictionary == null)
-                throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
+                throw new ArgumentNullException(nameof(dictionary));
 
 
             foreach (DictionaryEntry entry in dictionary)
             foreach (DictionaryEntry entry in dictionary)
                 Add(entry.Key, entry.Value);
                 Add(entry.Key, entry.Value);
@@ -41,7 +42,9 @@ namespace Godot.Collections
 
 
         private Dictionary(godot_dictionary nativeValueToOwn)
         private Dictionary(godot_dictionary nativeValueToOwn)
         {
         {
-            NativeValue = nativeValueToOwn;
+            NativeValue = (godot_dictionary.movable)(nativeValueToOwn.IsAllocated ?
+                nativeValueToOwn :
+                NativeFuncs.godotsharp_dictionary_new());
         }
         }
 
 
         // Explicit name to make it very clear
         // Explicit name to make it very clear
@@ -65,7 +68,7 @@ namespace Godot.Collections
         public void Dispose(bool disposing)
         public void Dispose(bool disposing)
         {
         {
             // Always dispose `NativeValue` even if disposing is true
             // Always dispose `NativeValue` even if disposing is true
-            NativeValue.Dispose();
+            NativeValue.DangerousSelfRef.Dispose();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -76,7 +79,8 @@ namespace Godot.Collections
         public Dictionary Duplicate(bool deep = false)
         public Dictionary Duplicate(bool deep = false)
         {
         {
             godot_dictionary newDictionary;
             godot_dictionary newDictionary;
-            NativeFuncs.godotsharp_dictionary_duplicate(ref NativeValue, deep.ToGodotBool(), out newDictionary);
+            var self = (godot_dictionary)NativeValue;
+            NativeFuncs.godotsharp_dictionary_duplicate(ref self, deep.ToGodotBool(), out newDictionary);
             return CreateTakingOwnershipOfDisposableValue(newDictionary);
             return CreateTakingOwnershipOfDisposableValue(newDictionary);
         }
         }
 
 
@@ -90,7 +94,8 @@ namespace Godot.Collections
             get
             get
             {
             {
                 godot_array keysArray;
                 godot_array keysArray;
-                NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray);
+                var self = (godot_dictionary)NativeValue;
+                NativeFuncs.godotsharp_dictionary_keys(ref self, out keysArray);
                 return Array.CreateTakingOwnershipOfDisposableValue(keysArray);
                 return Array.CreateTakingOwnershipOfDisposableValue(keysArray);
             }
             }
         }
         }
@@ -103,22 +108,25 @@ namespace Godot.Collections
             get
             get
             {
             {
                 godot_array valuesArray;
                 godot_array valuesArray;
-                NativeFuncs.godotsharp_dictionary_values(ref NativeValue, out valuesArray);
+                var self = (godot_dictionary)NativeValue;
+                NativeFuncs.godotsharp_dictionary_values(ref self, out valuesArray);
                 return Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
                 return Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
             }
             }
         }
         }
 
 
         private (Array keys, Array values, int count) GetKeyValuePairs()
         private (Array keys, Array values, int count) GetKeyValuePairs()
         {
         {
+            var self = (godot_dictionary)NativeValue;
+
             godot_array keysArray;
             godot_array keysArray;
-            NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray);
+            NativeFuncs.godotsharp_dictionary_keys(ref self, out keysArray);
             var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
             var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
 
 
             godot_array valuesArray;
             godot_array valuesArray;
-            NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out valuesArray);
+            NativeFuncs.godotsharp_dictionary_keys(ref self, out valuesArray);
             var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
             var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
 
 
-            int count = NativeFuncs.godotsharp_dictionary_count(ref NativeValue);
+            int count = NativeFuncs.godotsharp_dictionary_count(ref self);
 
 
             return (keys, values, count);
             return (keys, values, count);
         }
         }
@@ -131,16 +139,17 @@ namespace Godot.Collections
         /// Returns the object at the given <paramref name="key"/>.
         /// Returns the object at the given <paramref name="key"/>.
         /// </summary>
         /// </summary>
         /// <value>The object at the given <paramref name="key"/>.</value>
         /// <value>The object at the given <paramref name="key"/>.</value>
-        public unsafe object this[object key]
+        public object this[object key]
         {
         {
             get
             get
             {
             {
-                using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
-                if (NativeFuncs.godotsharp_dictionary_try_get_value(ref NativeValue, &variantKey,
-                    out godot_variant value).ToBool())
+                using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+                var self = (godot_dictionary)NativeValue;
+                if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self, variantKey,
+                        out godot_variant value).ToBool())
                 {
                 {
                     using (value)
                     using (value)
-                        return Marshaling.variant_to_mono_object(&value);
+                        return Marshaling.ConvertVariantToManagedObject(value);
                 }
                 }
                 else
                 else
                 {
                 {
@@ -149,9 +158,10 @@ namespace Godot.Collections
             }
             }
             set
             set
             {
             {
-                using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
-                using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
-                NativeFuncs.godotsharp_dictionary_set_value(ref NativeValue, &variantKey, &variantValue);
+                using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+                using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+                var self = (godot_dictionary)NativeValue;
+                NativeFuncs.godotsharp_dictionary_set_value(ref self, variantKey, variantValue);
             }
             }
         }
         }
 
 
@@ -161,31 +171,38 @@ namespace Godot.Collections
         /// </summary>
         /// </summary>
         /// <param name="key">The key at which to add the object.</param>
         /// <param name="key">The key at which to add the object.</param>
         /// <param name="value">The object to add.</param>
         /// <param name="value">The object to add.</param>
-        public unsafe void Add(object key, object value)
+        public void Add(object key, object value)
         {
         {
-            using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
+            using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+
+            var self = (godot_dictionary)NativeValue;
 
 
-            if (NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey).ToBool())
+            if (NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool())
                 throw new ArgumentException("An element with the same key already exists", nameof(key));
                 throw new ArgumentException("An element with the same key already exists", nameof(key));
 
 
-            using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
-            NativeFuncs.godotsharp_dictionary_add(ref NativeValue, &variantKey, &variantValue);
+            using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+            NativeFuncs.godotsharp_dictionary_add(ref self, variantKey, variantValue);
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Erases all items from this <see cref="Dictionary"/>.
         /// Erases all items from this <see cref="Dictionary"/>.
         /// </summary>
         /// </summary>
-        public void Clear() => NativeFuncs.godotsharp_dictionary_clear(ref NativeValue);
+        public void Clear()
+        {
+            var self = (godot_dictionary)NativeValue;
+            NativeFuncs.godotsharp_dictionary_clear(ref self);
+        }
 
 
         /// <summary>
         /// <summary>
         /// Checks if this <see cref="Dictionary"/> contains the given key.
         /// Checks if this <see cref="Dictionary"/> contains the given key.
         /// </summary>
         /// </summary>
         /// <param name="key">The key to look for.</param>
         /// <param name="key">The key to look for.</param>
         /// <returns>Whether or not this dictionary contains the given key.</returns>
         /// <returns>Whether or not this dictionary contains the given key.</returns>
-        public unsafe bool Contains(object key)
+        public bool Contains(object key)
         {
         {
-            using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
-            return NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey).ToBool();
+            using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+            var self = (godot_dictionary)NativeValue;
+            return NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -198,10 +215,11 @@ namespace Godot.Collections
         /// Removes an element from this <see cref="Dictionary"/> by key.
         /// Removes an element from this <see cref="Dictionary"/> by key.
         /// </summary>
         /// </summary>
         /// <param name="key">The key of the element to remove.</param>
         /// <param name="key">The key of the element to remove.</param>
-        public unsafe void Remove(object key)
+        public void Remove(object key)
         {
         {
-            using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
-            NativeFuncs.godotsharp_dictionary_remove_key(ref NativeValue, &variantKey);
+            using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+            var self = (godot_dictionary)NativeValue;
+            NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey);
         }
         }
 
 
         // ICollection
         // ICollection
@@ -215,7 +233,14 @@ namespace Godot.Collections
         /// This is also known as the size or length of the dictionary.
         /// This is also known as the size or length of the dictionary.
         /// </summary>
         /// </summary>
         /// <returns>The number of elements.</returns>
         /// <returns>The number of elements.</returns>
-        public int Count => NativeFuncs.godotsharp_dictionary_count(ref NativeValue);
+        public int Count
+        {
+            get
+            {
+                var self = (godot_dictionary)NativeValue;
+                return NativeFuncs.godotsharp_dictionary_count(ref self);
+            }
+        }
 
 
         /// <summary>
         /// <summary>
         /// Copies the elements of this <see cref="Dictionary"/> to the given
         /// Copies the elements of this <see cref="Dictionary"/> to the given
@@ -279,17 +304,19 @@ namespace Godot.Collections
                 }
                 }
             }
             }
 
 
-            private unsafe void UpdateEntry()
+            private void UpdateEntry()
             {
             {
                 _dirty = false;
                 _dirty = false;
-                NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref _dictionary.NativeValue, _index,
+                var self = (godot_dictionary)_dictionary.NativeValue;
+                NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, _index,
                     out godot_variant key,
                     out godot_variant key,
                     out godot_variant value);
                     out godot_variant value);
                 using (key)
                 using (key)
                 using (value)
                 using (value)
                 {
                 {
-                    _entry = new DictionaryEntry(Marshaling.variant_to_mono_object(&key),
-                        Marshaling.variant_to_mono_object(&value));
+                    // FIXME: DictionaryEntry keys cannot be null, but Godot dictionaries allow null keys
+                    _entry = new DictionaryEntry(Marshaling.ConvertVariantToManagedObject(key)!,
+                        Marshaling.ConvertVariantToManagedObject(value));
                 }
                 }
             }
             }
 
 
@@ -315,11 +342,12 @@ namespace Godot.Collections
         /// Converts this <see cref="Dictionary"/> to a string.
         /// Converts this <see cref="Dictionary"/> to a string.
         /// </summary>
         /// </summary>
         /// <returns>A string representation of this dictionary.</returns>
         /// <returns>A string representation of this dictionary.</returns>
-        public override unsafe string ToString()
+        public override string ToString()
         {
         {
-            using godot_string str = default;
-            NativeFuncs.godotsharp_dictionary_to_string(ref NativeValue, &str);
-            return Marshaling.mono_string_from_godot(str);
+            var self = (godot_dictionary)NativeValue;
+            NativeFuncs.godotsharp_dictionary_to_string(ref self, out godot_string str);
+            using (str)
+                return Marshaling.ConvertStringToManaged(str);
         }
         }
     }
     }
 
 
@@ -345,7 +373,11 @@ namespace Godot.Collections
     {
     {
         private readonly Dictionary _underlyingDict;
         private readonly Dictionary _underlyingDict;
 
 
-        internal ref godot_dictionary NativeValue => ref _underlyingDict.NativeValue;
+        internal ref godot_dictionary.movable NativeValue
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => ref _underlyingDict.NativeValue;
+        }
 
 
         // ReSharper disable StaticMemberInGenericType
         // ReSharper disable StaticMemberInGenericType
         // Warning is about unique static fields being created for each generic type combination:
         // Warning is about unique static fields being created for each generic type combination:
@@ -375,10 +407,10 @@ namespace Godot.Collections
         /// <returns>A new Godot Dictionary.</returns>
         /// <returns>A new Godot Dictionary.</returns>
         public Dictionary(IDictionary<TKey, TValue> dictionary)
         public Dictionary(IDictionary<TKey, TValue> dictionary)
         {
         {
-            _underlyingDict = new Dictionary();
-
             if (dictionary == null)
             if (dictionary == null)
-                throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
+                throw new ArgumentNullException(nameof(dictionary));
+
+            _underlyingDict = new Dictionary();
 
 
             foreach (KeyValuePair<TKey, TValue> entry in dictionary)
             foreach (KeyValuePair<TKey, TValue> entry in dictionary)
                 Add(entry.Key, entry.Value);
                 Add(entry.Key, entry.Value);
@@ -405,7 +437,7 @@ namespace Godot.Collections
         /// <param name="from">The typed dictionary to convert.</param>
         /// <param name="from">The typed dictionary to convert.</param>
         public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
         public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
         {
         {
-            return from._underlyingDict;
+            return from?._underlyingDict;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -428,19 +460,17 @@ namespace Godot.Collections
         {
         {
             get
             get
             {
             {
-                unsafe
+                using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+                var self = (godot_dictionary)_underlyingDict.NativeValue;
+                if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
+                        variantKey, out godot_variant value).ToBool())
                 {
                 {
-                    using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
-                    if (NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
-                        &variantKey, out godot_variant value).ToBool())
-                    {
-                        using (value)
-                            return (TValue)Marshaling.variant_to_mono_object_of_type(&value, TypeOfValues);
-                    }
-                    else
-                    {
-                        throw new KeyNotFoundException();
-                    }
+                    using (value)
+                        return (TValue)Marshaling.ConvertVariantToManagedObjectOfType(value, TypeOfValues);
+                }
+                else
+                {
+                    throw new KeyNotFoundException();
                 }
                 }
             }
             }
             set => _underlyingDict[key] = value;
             set => _underlyingDict[key] = value;
@@ -454,7 +484,8 @@ namespace Godot.Collections
             get
             get
             {
             {
                 godot_array keyArray;
                 godot_array keyArray;
-                NativeFuncs.godotsharp_dictionary_keys(ref _underlyingDict.NativeValue, out keyArray);
+                var self = (godot_dictionary)_underlyingDict.NativeValue;
+                NativeFuncs.godotsharp_dictionary_keys(ref self, out keyArray);
                 return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray);
                 return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray);
             }
             }
         }
         }
@@ -467,21 +498,23 @@ namespace Godot.Collections
             get
             get
             {
             {
                 godot_array valuesArray;
                 godot_array valuesArray;
-                NativeFuncs.godotsharp_dictionary_values(ref _underlyingDict.NativeValue, out valuesArray);
+                var self = (godot_dictionary)_underlyingDict.NativeValue;
+                NativeFuncs.godotsharp_dictionary_values(ref self, out valuesArray);
                 return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray);
                 return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray);
             }
             }
         }
         }
 
 
-        private unsafe KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
+        private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
         {
         {
-            NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref _underlyingDict.NativeValue, index,
+            var self = (godot_dictionary)_underlyingDict.NativeValue;
+            NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index,
                 out godot_variant key,
                 out godot_variant key,
                 out godot_variant value);
                 out godot_variant value);
             using (key)
             using (key)
             using (value)
             using (value)
             {
             {
-                return new KeyValuePair<TKey, TValue>((TKey)Marshaling.variant_to_mono_object(&key),
-                    (TValue)Marshaling.variant_to_mono_object(&value));
+                return new KeyValuePair<TKey, TValue>((TKey)Marshaling.ConvertVariantToManagedObject(key),
+                    (TValue)Marshaling.ConvertVariantToManagedObject(value));
             }
             }
         }
         }
 
 
@@ -510,10 +543,11 @@ namespace Godot.Collections
         /// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
         /// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
         /// </summary>
         /// </summary>
         /// <param name="key">The key of the element to remove.</param>
         /// <param name="key">The key of the element to remove.</param>
-        public unsafe bool Remove(TKey key)
+        public bool Remove(TKey key)
         {
         {
-            using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
-            return NativeFuncs.godotsharp_dictionary_remove_key(ref _underlyingDict.NativeValue, &variantKey).ToBool();
+            using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+            var self = (godot_dictionary)_underlyingDict.NativeValue;
+            return NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey).ToBool();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -522,16 +556,17 @@ namespace Godot.Collections
         /// <param name="key">The key of the element to get.</param>
         /// <param name="key">The key of the element to get.</param>
         /// <param name="value">The value at the given <paramref name="key"/>.</param>
         /// <param name="value">The value at the given <paramref name="key"/>.</param>
         /// <returns>If an object was found for the given <paramref name="key"/>.</returns>
         /// <returns>If an object was found for the given <paramref name="key"/>.</returns>
-        public unsafe bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
+        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
         {
         {
-            using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
-            bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
-                &variantKey, out godot_variant retValue).ToBool();
+            using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+            var self = (godot_dictionary)_underlyingDict.NativeValue;
+            bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
+                variantKey, out godot_variant retValue).ToBool();
 
 
             using (retValue)
             using (retValue)
             {
             {
                 value = found ?
                 value = found ?
-                    (TValue)Marshaling.variant_to_mono_object_of_type(&retValue, TypeOfValues) :
+                    (TValue)Marshaling.ConvertVariantToManagedObjectOfType(retValue, TypeOfValues) :
                     default;
                     default;
             }
             }
 
 
@@ -562,19 +597,20 @@ namespace Godot.Collections
             _underlyingDict.Clear();
             _underlyingDict.Clear();
         }
         }
 
 
-        unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
         {
         {
-            using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key);
-            bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
-                &variantKey, out godot_variant retValue).ToBool();
+            using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
+            var self = (godot_dictionary)_underlyingDict.NativeValue;
+            bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
+                variantKey, out godot_variant retValue).ToBool();
 
 
             using (retValue)
             using (retValue)
             {
             {
                 if (!found)
                 if (!found)
                     return false;
                     return false;
 
 
-                using godot_variant variantValue = Marshaling.mono_object_to_variant(item.Value);
-                return NativeFuncs.godotsharp_variant_equals(&variantValue, &retValue).ToBool();
+                using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
+                return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();
             }
             }
         }
         }
 
 
@@ -606,22 +642,23 @@ namespace Godot.Collections
             }
             }
         }
         }
 
 
-        unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
+        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
         {
         {
-            using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key);
-            bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
-                &variantKey, out godot_variant retValue).ToBool();
+            using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
+            var self = (godot_dictionary)_underlyingDict.NativeValue;
+            bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
+                variantKey, out godot_variant retValue).ToBool();
 
 
             using (retValue)
             using (retValue)
             {
             {
                 if (!found)
                 if (!found)
                     return false;
                     return false;
 
 
-                using godot_variant variantValue = Marshaling.mono_object_to_variant(item.Value);
-                if (NativeFuncs.godotsharp_variant_equals(&variantValue, &retValue).ToBool())
+                using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
+                if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())
                 {
                 {
                     return NativeFuncs.godotsharp_dictionary_remove_key(
                     return NativeFuncs.godotsharp_dictionary_remove_key(
-                        ref _underlyingDict.NativeValue, &variantKey).ToBool();
+                        ref self, variantKey).ToBool();
                 }
                 }
 
 
                 return false;
                 return false;

+ 6 - 9
modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ObjectExtensions.cs

@@ -35,17 +35,14 @@ namespace Godot
             if (!IsInstanceValid(obj))
             if (!IsInstanceValid(obj))
                 return null;
                 return null;
 
 
-            using godot_ref weakRef = default;
-
-            unsafe
+            NativeFuncs.godotsharp_weakref(GetPtr(obj), out godot_ref weakRef);
+            using (weakRef)
             {
             {
-                NativeFuncs.godotsharp_weakref(GetPtr(obj), &weakRef);
-            }
+                if (weakRef.IsNull)
+                    return null;
 
 
-            if (weakRef.IsNull)
-                return null;
-
-            return (WeakRef)InteropUtils.UnmanagedGetManaged(weakRef._reference);
+                return (WeakRef)InteropUtils.UnmanagedGetManaged(weakRef.Reference);
+            }
         }
         }
     }
     }
 }
 }

+ 8 - 10
modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs

@@ -1,5 +1,4 @@
 using System.Reflection;
 using System.Reflection;
-using System.Runtime.CompilerServices;
 using Godot.Collections;
 using Godot.Collections;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 
 
@@ -11,7 +10,7 @@ namespace Godot
         /// Returns a list of all nodes assigned to the given <paramref name="group"/>.
         /// Returns a list of all nodes assigned to the given <paramref name="group"/>.
         /// </summary>
         /// </summary>
         /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
         /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
-        public unsafe Array<T> GetNodesInGroup<T>(StringName group) where T : class
+        public Array<T> GetNodesInGroup<T>(StringName group) where T : class
         {
         {
             var array = GetNodesInGroup(group);
             var array = GetNodesInGroup(group);
 
 
@@ -29,19 +28,18 @@ namespace Godot
                     BindingFlags.Public | BindingFlags.NonPublic);
                     BindingFlags.Public | BindingFlags.NonPublic);
 
 
                 var nativeName = (StringName)field!.GetValue(null);
                 var nativeName = (StringName)field!.GetValue(null);
-                godot_string_name nativeNameAux = nativeName.NativeValue;
-                godot_array inputAux = array.NativeValue;
-                godot_array filteredArray;
-                NativeFuncs.godotsharp_array_filter_godot_objects_by_native(
-                    &nativeNameAux, &inputAux, &filteredArray);
+                var nativeNameSelf = (godot_string_name)nativeName!.NativeValue;
+                var inputSelf = (godot_array)array.NativeValue;
+                NativeFuncs.godotsharp_array_filter_godot_objects_by_native(nativeNameSelf, inputSelf,
+                    out godot_array filteredArray);
                 return Array<T>.CreateTakingOwnershipOfDisposableValue(filteredArray);
                 return Array<T>.CreateTakingOwnershipOfDisposableValue(filteredArray);
             }
             }
             else
             else
             {
             {
                 // Custom derived type
                 // Custom derived type
-                godot_array inputAux = array.NativeValue;
-                godot_array filteredArray;
-                NativeFuncs.godotsharp_array_filter_godot_objects_by_non_native(&inputAux, &filteredArray);
+                var inputSelf = (godot_array)array.NativeValue;
+                NativeFuncs.godotsharp_array_filter_godot_objects_by_non_native(inputSelf,
+                    out godot_array filteredArray);
 
 
                 var filteredArrayWrapped = Array.CreateTakingOwnershipOfDisposableValue(filteredArray);
                 var filteredArrayWrapped = Array.CreateTakingOwnershipOfDisposableValue(filteredArray);
 
 

+ 57 - 58
modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs

@@ -26,12 +26,12 @@ namespace Godot
         /// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param>
         /// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param>
         /// <param name="allowObjects">If objects should be decoded.</param>
         /// <param name="allowObjects">If objects should be decoded.</param>
         /// <returns>The decoded <c>Variant</c>.</returns>
         /// <returns>The decoded <c>Variant</c>.</returns>
-        public static unsafe object Bytes2Var(byte[] bytes, bool allowObjects = false)
+        public static object Bytes2Var(byte[] bytes, bool allowObjects = false)
         {
         {
-            using var varBytes = Marshaling.mono_array_to_PackedByteArray(bytes);
-            using godot_variant ret = default;
-            NativeFuncs.godotsharp_bytes2var(&varBytes, allowObjects.ToGodotBool(), &ret);
-            return Marshaling.variant_to_mono_object(&ret);
+            using var varBytes = Marshaling.ConvertSystemArrayToNativePackedByteArray(bytes);
+            NativeFuncs.godotsharp_bytes2var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret);
+            using (ret)
+                return Marshaling.ConvertVariantToManagedObject(ret);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -49,12 +49,12 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <returns>The <c>Variant</c> converted to the given <paramref name="type"/>.</returns>
         /// <returns>The <c>Variant</c> converted to the given <paramref name="type"/>.</returns>
-        public static unsafe object Convert(object what, Variant.Type type)
+        public static object Convert(object what, Variant.Type type)
         {
         {
-            using var whatVariant = Marshaling.mono_object_to_variant(what);
-            using godot_variant ret = default;
-            NativeFuncs.godotsharp_convert(&whatVariant, (int)type, &ret);
-            return Marshaling.variant_to_mono_object(&ret);
+            using var whatVariant = Marshaling.ConvertManagedObjectToVariant(what);
+            NativeFuncs.godotsharp_convert(whatVariant, (int)type, out godot_variant ret);
+            using (ret)
+                return Marshaling.ConvertVariantToManagedObject(ret);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -88,10 +88,10 @@ namespace Godot
         /// </example>
         /// </example>
         /// <param name="var">Variable that will be hashed.</param>
         /// <param name="var">Variable that will be hashed.</param>
         /// <returns>Hash of the variable passed.</returns>
         /// <returns>Hash of the variable passed.</returns>
-        public static unsafe int Hash(object var)
+        public static int Hash(object var)
         {
         {
-            using var variant = Marshaling.mono_object_to_variant(var);
-            return NativeFuncs.godotsharp_hash(&variant);
+            using var variant = Marshaling.ConvertManagedObjectToVariant(var);
+            return NativeFuncs.godotsharp_hash(variant);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -207,10 +207,10 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <param name="message">Error message.</param>
         /// <param name="message">Error message.</param>
-        public static unsafe void PushError(string message)
+        public static void PushError(string message)
         {
         {
-            using var godotStr = Marshaling.mono_string_to_godot(message);
-            NativeFuncs.godotsharp_pusherror(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(message);
+            NativeFuncs.godotsharp_pusherror(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -220,10 +220,10 @@ namespace Godot
         /// GD.PushWarning("test warning"); // Prints "test warning" to debugger and terminal as warning call
         /// GD.PushWarning("test warning"); // Prints "test warning" to debugger and terminal as warning call
         /// </example>
         /// </example>
         /// <param name="message">Warning message.</param>
         /// <param name="message">Warning message.</param>
-        public static unsafe void PushWarning(string message)
+        public static void PushWarning(string message)
         {
         {
-            using var godotStr = Marshaling.mono_string_to_godot(message);
-            NativeFuncs.godotsharp_pushwarning(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(message);
+            NativeFuncs.godotsharp_pushwarning(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -242,11 +242,11 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <param name="what">Arguments that will be printed.</param>
         /// <param name="what">Arguments that will be printed.</param>
-        public static unsafe void Print(params object[] what)
+        public static void Print(params object[] what)
         {
         {
             string str = string.Concat(GetPrintParams(what));
             string str = string.Concat(GetPrintParams(what));
-            using var godotStr = Marshaling.mono_string_to_godot(str);
-            NativeFuncs.godotsharp_print(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(str);
+            NativeFuncs.godotsharp_print(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -273,11 +273,11 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <param name="what">Arguments that will be printed.</param>
         /// <param name="what">Arguments that will be printed.</param>
-        public static unsafe void PrintRich(params object[] what)
+        public static void PrintRich(params object[] what)
         {
         {
             string str = string.Concat(GetPrintParams(what));
             string str = string.Concat(GetPrintParams(what));
-            using var godotStr = Marshaling.mono_string_to_godot(str);
-            NativeFuncs.godotsharp_print_rich(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(str);
+            NativeFuncs.godotsharp_print_rich(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -297,11 +297,11 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <param name="what">Arguments that will be printed.</param>
         /// <param name="what">Arguments that will be printed.</param>
-        public static unsafe void PrintErr(params object[] what)
+        public static void PrintErr(params object[] what)
         {
         {
             string str = string.Concat(GetPrintParams(what));
             string str = string.Concat(GetPrintParams(what));
-            using var godotStr = Marshaling.mono_string_to_godot(str);
-            NativeFuncs.godotsharp_printerr(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(str);
+            NativeFuncs.godotsharp_printerr(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -319,11 +319,11 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <param name="what">Arguments that will be printed.</param>
         /// <param name="what">Arguments that will be printed.</param>
-        public static unsafe void PrintRaw(params object[] what)
+        public static void PrintRaw(params object[] what)
         {
         {
             string str = string.Concat(GetPrintParams(what));
             string str = string.Concat(GetPrintParams(what));
-            using var godotStr = Marshaling.mono_string_to_godot(str);
-            NativeFuncs.godotsharp_printraw(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(str);
+            NativeFuncs.godotsharp_printraw(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -335,11 +335,11 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <param name="what">Arguments that will be printed.</param>
         /// <param name="what">Arguments that will be printed.</param>
-        public static unsafe void PrintS(params object[] what)
+        public static void PrintS(params object[] what)
         {
         {
             string str = string.Join(' ', GetPrintParams(what));
             string str = string.Join(' ', GetPrintParams(what));
-            using var godotStr = Marshaling.mono_string_to_godot(str);
-            NativeFuncs.godotsharp_prints(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(str);
+            NativeFuncs.godotsharp_prints(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -351,11 +351,11 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <param name="what">Arguments that will be printed.</param>
         /// <param name="what">Arguments that will be printed.</param>
-        public static unsafe void PrintT(params object[] what)
+        public static void PrintT(params object[] what)
         {
         {
             string str = string.Join('\t', GetPrintParams(what));
             string str = string.Join('\t', GetPrintParams(what));
-            using var godotStr = Marshaling.mono_string_to_godot(str);
-            NativeFuncs.godotsharp_printt(&godotStr);
+            using var godotStr = Marshaling.ConvertStringToNative(str);
+            NativeFuncs.godotsharp_printt(godotStr);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -520,12 +520,12 @@ namespace Godot
         /// </summary>
         /// </summary>
         /// <param name="what">Arguments that will converted to string.</param>
         /// <param name="what">Arguments that will converted to string.</param>
         /// <returns>The string formed by the given arguments.</returns>
         /// <returns>The string formed by the given arguments.</returns>
-        public static unsafe string Str(params object[] what)
+        public static string Str(params object[] what)
         {
         {
-            using var whatGodotArray = Marshaling.mono_array_to_Array(what);
-            using godot_string ret = default;
-            NativeFuncs.godotsharp_str(&whatGodotArray, &ret);
-            return Marshaling.mono_string_from_godot(ret);
+            using var whatGodotArray = Marshaling.ConvertSystemArrayToNativeGodotArray(what);
+            NativeFuncs.godotsharp_str(whatGodotArray, out godot_string ret);
+            using (ret)
+                return Marshaling.ConvertStringToManaged(ret);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -540,12 +540,12 @@ namespace Godot
         /// </example>
         /// </example>
         /// <param name="str">String that will be converted to Variant.</param>
         /// <param name="str">String that will be converted to Variant.</param>
         /// <returns>The decoded <c>Variant</c>.</returns>
         /// <returns>The decoded <c>Variant</c>.</returns>
-        public static unsafe object Str2Var(string str)
+        public static object Str2Var(string str)
         {
         {
-            using var godotStr = Marshaling.mono_string_to_godot(str);
-            using godot_variant ret = default;
-            NativeFuncs.godotsharp_str2var(&godotStr, &ret);
-            return Marshaling.variant_to_mono_object(&ret);
+            using var godotStr = Marshaling.ConvertStringToNative(str);
+            NativeFuncs.godotsharp_str2var(godotStr, out godot_variant ret);
+            using (ret)
+                return Marshaling.ConvertVariantToManagedObject(ret);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -557,13 +557,12 @@ namespace Godot
         /// <param name="var">Variant that will be encoded.</param>
         /// <param name="var">Variant that will be encoded.</param>
         /// <param name="fullObjects">If objects should be serialized.</param>
         /// <param name="fullObjects">If objects should be serialized.</param>
         /// <returns>The <c>Variant</c> encoded as an array of bytes.</returns>
         /// <returns>The <c>Variant</c> encoded as an array of bytes.</returns>
-        public static unsafe byte[] Var2Bytes(object var, bool fullObjects = false)
+        public static byte[] Var2Bytes(object var, bool fullObjects = false)
         {
         {
-            using var variant = Marshaling.mono_object_to_variant(var);
-            using godot_packed_byte_array varBytes = default;
-            NativeFuncs.godotsharp_var2bytes(&variant, fullObjects.ToGodotBool(), &varBytes);
+            using var variant = Marshaling.ConvertManagedObjectToVariant(var);
+            NativeFuncs.godotsharp_var2bytes(variant, fullObjects.ToGodotBool(), out var varBytes);
             using (varBytes)
             using (varBytes)
-                return Marshaling.PackedByteArray_to_mono_array(&varBytes);
+                return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -583,12 +582,12 @@ namespace Godot
         /// </example>
         /// </example>
         /// <param name="var">Variant that will be converted to string.</param>
         /// <param name="var">Variant that will be converted to string.</param>
         /// <returns>The <c>Variant</c> encoded as a string.</returns>
         /// <returns>The <c>Variant</c> encoded as a string.</returns>
-        public static unsafe string Var2Str(object var)
+        public static string Var2Str(object var)
         {
         {
-            using var variant = Marshaling.mono_object_to_variant(var);
-            using godot_string ret = default;
-            NativeFuncs.godotsharp_var2str(&variant, &ret);
-            return Marshaling.mono_string_from_godot(ret);
+            using var variant = Marshaling.ConvertManagedObjectToVariant(var);
+            NativeFuncs.godotsharp_var2str(variant, out godot_string ret);
+            using (ret)
+                return Marshaling.ConvertStringToManaged(ret);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -597,7 +596,7 @@ namespace Godot
         /// <returns>The <see cref="Variant.Type"/> for the given <paramref name="type"/>.</returns>
         /// <returns>The <see cref="Variant.Type"/> for the given <paramref name="type"/>.</returns>
         public static Variant.Type TypeToVariantType(Type type)
         public static Variant.Type TypeToVariantType(Type type)
         {
         {
-            return Marshaling.managed_to_variant_type(type, out bool _);
+            return Marshaling.ConvertManagedTypeToVariantType(type, out bool _);
         }
         }
     }
     }
 }
 }

+ 595 - 97
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs

@@ -10,7 +10,10 @@ using System.Runtime.InteropServices;
 
 
 namespace Godot.NativeInterop
 namespace Godot.NativeInterop
 {
 {
-    internal static class GodotBoolExtensions
+    // NOTES:
+    // ref structs cannot implement interfaces, but they still work in `using` directives if they declare Dispose()
+
+    public static class GodotBoolExtensions
     {
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static unsafe godot_bool ToGodotBool(this bool @bool)
         public static unsafe godot_bool ToGodotBool(this bool @bool)
@@ -35,9 +38,9 @@ namespace Godot.NativeInterop
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_ref : IDisposable
+    public ref struct godot_ref
     {
     {
-        internal IntPtr _reference;
+        private IntPtr _reference;
 
 
         public void Dispose()
         public void Dispose()
         {
         {
@@ -47,7 +50,17 @@ namespace Godot.NativeInterop
             _reference = IntPtr.Zero;
             _reference = IntPtr.Zero;
         }
         }
 
 
-        public bool IsNull => _reference == IntPtr.Zero;
+        public readonly IntPtr Reference
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _reference;
+        }
+
+        public readonly bool IsNull
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _reference == IntPtr.Zero;
+        }
     }
     }
 
 
     [SuppressMessage("ReSharper", "InconsistentNaming")]
     [SuppressMessage("ReSharper", "InconsistentNaming")]
@@ -63,41 +76,53 @@ namespace Godot.NativeInterop
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_variant_call_error
+    public ref struct godot_variant_call_error
     {
     {
-        public godot_variant_call_error_error error;
-        public int argument;
-        public int expected;
+        private godot_variant_call_error_error error;
+        private int argument;
+        private int expected;
+
+        public godot_variant_call_error_error Error
+        {
+            readonly get => error;
+            set => error = value;
+        }
+
+        public int Argument
+        {
+            readonly get => argument;
+            set => argument = value;
+        }
+
+        public Godot.Variant.Type Expected
+        {
+            readonly get => (Godot.Variant.Type)expected;
+            set => expected = (int)value;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Explicit)]
     [StructLayout(LayoutKind.Explicit)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_variant : IDisposable
+    public ref struct godot_variant
     {
     {
         // 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.
         // 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;
         [FieldOffset(0)] private int _typeField;
 
 
         // There's padding here
         // There's padding here
 
 
-        [FieldOffset(8)] internal godot_variant_data _data;
-
-        public Variant.Type _type
-        {
-            get => (Variant.Type)_typeField;
-            set => _typeField = (int)value;
-        }
+        [FieldOffset(8)] private godot_variant_data _data;
 
 
         [StructLayout(LayoutKind.Explicit)]
         [StructLayout(LayoutKind.Explicit)]
         // ReSharper disable once InconsistentNaming
         // ReSharper disable once InconsistentNaming
-        internal unsafe struct godot_variant_data
+        private unsafe ref struct godot_variant_data
         {
         {
             [FieldOffset(0)] public godot_bool _bool;
             [FieldOffset(0)] public godot_bool _bool;
             [FieldOffset(0)] public long _int;
             [FieldOffset(0)] public long _int;
             [FieldOffset(0)] public double _float;
             [FieldOffset(0)] public double _float;
-            [FieldOffset(0)] public Transform2D* _transform2d;
+            [FieldOffset(0)] public Transform2D* _transform2D;
             [FieldOffset(0)] public AABB* _aabb;
             [FieldOffset(0)] public AABB* _aabb;
             [FieldOffset(0)] public Basis* _basis;
             [FieldOffset(0)] public Basis* _basis;
-            [FieldOffset(0)] public Transform3D* _transform3d;
+            [FieldOffset(0)] public Transform3D* _transform3D;
             [FieldOffset(0)] public Vector4* _vector4;
             [FieldOffset(0)] public Vector4* _vector4;
             [FieldOffset(0)] public Vector4i* _vector4i;
             [FieldOffset(0)] public Vector4i* _vector4i;
             [FieldOffset(0)] public Projection* _projection;
             [FieldOffset(0)] public Projection* _projection;
@@ -125,7 +150,7 @@ namespace Godot.NativeInterop
 
 
             [StructLayout(LayoutKind.Sequential)]
             [StructLayout(LayoutKind.Sequential)]
             // ReSharper disable once InconsistentNaming
             // ReSharper disable once InconsistentNaming
-            internal struct godot_variant_obj_data
+            public struct godot_variant_obj_data
             {
             {
                 public UInt64 id;
                 public UInt64 id;
                 public IntPtr obj;
                 public IntPtr obj;
@@ -133,7 +158,7 @@ namespace Godot.NativeInterop
 
 
             [StructLayout(LayoutKind.Sequential)]
             [StructLayout(LayoutKind.Sequential)]
             // ReSharper disable once InconsistentNaming
             // ReSharper disable once InconsistentNaming
-            private struct godot_variant_data_mem
+            public struct godot_variant_data_mem
             {
             {
 #pragma warning disable 169
 #pragma warning disable 169
                 private real_t _mem0;
                 private real_t _mem0;
@@ -144,9 +169,225 @@ namespace Godot.NativeInterop
             }
             }
         }
         }
 
 
+        public Variant.Type Type
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => (Variant.Type)_typeField;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _typeField = (int)value;
+        }
+
+        public godot_bool Bool
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._bool;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._bool = value;
+        }
+
+        public long Int
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._int;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._int = value;
+        }
+
+        public double Float
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._float;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._float = value;
+        }
+
+        public readonly unsafe Transform2D* Transform2D
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._transform2D;
+        }
+
+        public readonly unsafe AABB* AABB
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._aabb;
+        }
+
+        public readonly unsafe Basis* Basis
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._basis;
+        }
+
+        public readonly unsafe Transform3D* Transform3D
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._transform3D;
+        }
+
+        public readonly unsafe Vector4* Vector4
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._vector4;
+        }
+
+        public readonly unsafe Vector4i* Vector4i
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._vector4i;
+        }
+
+        public readonly unsafe Projection* Projection
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._projection;
+        }
+
+        public godot_string_name StringName
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_string_name;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_string_name = value;
+        }
+
+        public godot_string String
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_string;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_string = value;
+        }
+
+        public Vector3 Vector3
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_vector3;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_vector3 = value;
+        }
+
+        public Vector3i Vector3i
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_vector3i;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_vector3i = value;
+        }
+
+        public Vector2 Vector2
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_vector2;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_vector2 = value;
+        }
+
+        public Vector2i Vector2i
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_vector2i;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_vector2i = value;
+        }
+
+        public Rect2 Rect2
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_rect2;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_rect2 = value;
+        }
+
+        public Rect2i Rect2i
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_rect2i;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_rect2i = value;
+        }
+
+        public Plane Plane
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_plane;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_plane = value;
+        }
+
+        public Quaternion Quaternion
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_quaternion;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_quaternion = value;
+        }
+
+        public Color Color
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_color;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_color = value;
+        }
+
+        public godot_node_path NodePath
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_node_path;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_node_path = value;
+        }
+
+        public RID RID
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_rid;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_rid = value;
+        }
+
+        public godot_callable Callable
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_callable;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_callable = value;
+        }
+
+        public godot_signal Signal
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_signal;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_signal = value;
+        }
+
+        public godot_dictionary Dictionary
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_dictionary;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_dictionary = value;
+        }
+
+        public godot_array Array
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            readonly get => _data._m_array;
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set => _data._m_array = value;
+        }
+
+        public readonly IntPtr Object
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data._m_obj_data.obj;
+        }
+
         public void Dispose()
         public void Dispose()
         {
         {
-            switch (_type)
+            switch (Type)
             {
             {
                 case Variant.Type.Nil:
                 case Variant.Type.Nil:
                 case Variant.Type.Bool:
                 case Variant.Type.Bool:
@@ -166,15 +407,36 @@ namespace Godot.NativeInterop
             }
             }
 
 
             NativeFuncs.godotsharp_variant_destroy(ref this);
             NativeFuncs.godotsharp_variant_destroy(ref this);
-            _type = Variant.Type.Nil;
+            Type = Variant.Type.Nil;
+        }
+
+        [StructLayout(LayoutKind.Explicit)]
+        // ReSharper disable once InconsistentNaming
+        internal struct movable
+        {
+            // 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)] private godot_variant_data.godot_variant_data_mem _data;
+
+            public static unsafe explicit operator movable(in godot_variant value)
+                => *(movable*)CustomUnsafe.AsPointer(ref CustomUnsafe.AsRef(value));
+
+            public static unsafe explicit operator godot_variant(movable value)
+                => *(godot_variant*)Unsafe.AsPointer(ref value);
+
+            public unsafe ref godot_variant DangerousSelfRef =>
+                ref CustomUnsafe.AsRef((godot_variant*)Unsafe.AsPointer(ref this));
         }
         }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_string : IDisposable
+    public ref struct godot_string
     {
     {
-        internal IntPtr _ptr;
+        private IntPtr _ptr;
 
 
         public void Dispose()
         public void Dispose()
         {
         {
@@ -184,15 +446,25 @@ namespace Godot.NativeInterop
             _ptr = IntPtr.Zero;
             _ptr = IntPtr.Zero;
         }
         }
 
 
+        public readonly IntPtr Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
         // Size including the null termination character
         // Size including the null termination character
-        public unsafe int Size => _ptr != IntPtr.Zero ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != IntPtr.Zero ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_string_name : IDisposable
+    public ref struct godot_string_name
     {
     {
-        internal IntPtr _data;
+        private IntPtr _data;
 
 
         public void Dispose()
         public void Dispose()
         {
         {
@@ -202,18 +474,41 @@ namespace Godot.NativeInterop
             _data = IntPtr.Zero;
             _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) =>
+        public readonly bool IsAllocated
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data != IntPtr.Zero;
+        }
+
+        public readonly bool IsEmpty
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
             // This is all that's needed to check if it's empty. Equivalent to `== StringName()` in C++.
             // This is all that's needed to check if it's empty. Equivalent to `== StringName()` in C++.
-            name._data == IntPtr.Zero;
+            get => _data == IntPtr.Zero;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        // ReSharper disable once InconsistentNaming
+        internal struct movable
+        {
+            private IntPtr _data;
+
+            public static unsafe explicit operator movable(in godot_string_name value)
+                => *(movable*)CustomUnsafe.AsPointer(ref CustomUnsafe.AsRef(value));
+
+            public static unsafe explicit operator godot_string_name(movable value)
+                => *(godot_string_name*)Unsafe.AsPointer(ref value);
+
+            public unsafe ref godot_string_name DangerousSelfRef =>
+                ref CustomUnsafe.AsRef((godot_string_name*)Unsafe.AsPointer(ref this));
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_node_path : IDisposable
+    public ref struct godot_node_path
     {
     {
-        internal IntPtr _data;
+        private IntPtr _data;
 
 
         public void Dispose()
         public void Dispose()
         {
         {
@@ -223,49 +518,98 @@ namespace Godot.NativeInterop
             _data = IntPtr.Zero;
             _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) =>
+        public readonly bool IsAllocated
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _data != IntPtr.Zero;
+        }
+
+        public readonly bool IsEmpty
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
             // This is all that's needed to check if it's empty. It's what the `is_empty()` C++ method does.
             // 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;
+            get => _data == IntPtr.Zero;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        // ReSharper disable once InconsistentNaming
+        internal struct movable
+        {
+            private IntPtr _data;
+
+            public static unsafe explicit operator movable(in godot_node_path value)
+                => *(movable*)CustomUnsafe.AsPointer(ref CustomUnsafe.AsRef(value));
+
+            public static unsafe explicit operator godot_node_path(movable value)
+                => *(godot_node_path*)Unsafe.AsPointer(ref value);
+
+            public unsafe ref godot_node_path DangerousSelfRef =>
+                ref CustomUnsafe.AsRef((godot_node_path*)Unsafe.AsPointer(ref this));
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Explicit)]
     [StructLayout(LayoutKind.Explicit)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_signal : IDisposable
+    public ref struct godot_signal
     {
     {
-        [FieldOffset(0)] public godot_string_name _name;
+        [FieldOffset(0)] private godot_string_name _name;
 
 
         // There's padding here on 32-bit
         // There's padding here on 32-bit
 
 
-        [FieldOffset(8)] public UInt64 _objectId;
+        [FieldOffset(8)] private UInt64 _objectId;
+
+        public godot_signal(godot_string_name name, ulong objectId)
+        {
+            _name = name;
+            _objectId = objectId;
+        }
+
+        public godot_string_name Name
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _name;
+        }
+
+        public UInt64 ObjectId
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _objectId;
+        }
 
 
         public void Dispose()
         public void Dispose()
         {
         {
-            if (_name._data == IntPtr.Zero)
+            if (!_name.IsAllocated)
                 return;
                 return;
             NativeFuncs.godotsharp_signal_destroy(ref this);
             NativeFuncs.godotsharp_signal_destroy(ref this);
-            _name._data = IntPtr.Zero;
+            _name = default;
         }
         }
     }
     }
 
 
     [StructLayout(LayoutKind.Explicit)]
     [StructLayout(LayoutKind.Explicit)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_callable : IDisposable
+    public ref struct godot_callable
     {
     {
-        [FieldOffset(0)] public godot_string_name _method;
+        [FieldOffset(0)] private godot_string_name _method;
 
 
         // There's padding here on 32-bit
         // There's padding here on 32-bit
 
 
-        [FieldOffset(8)] public UInt64 _objectId;
-        [FieldOffset(8)] public IntPtr _custom;
+        // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+        [FieldOffset(8)] private UInt64 _objectId;
+        [FieldOffset(8)] private IntPtr _custom;
+
+        public godot_callable(godot_string_name method, ulong objectId) : this()
+        {
+            _method = method;
+            _objectId = objectId;
+        }
 
 
         public void Dispose()
         public void Dispose()
         {
         {
-            if (_method._data == IntPtr.Zero && _custom == IntPtr.Zero)
+            // _custom needs freeing as well
+            if (!_method.IsAllocated && _custom == IntPtr.Zero)
                 return;
                 return;
             NativeFuncs.godotsharp_callable_destroy(ref this);
             NativeFuncs.godotsharp_callable_destroy(ref this);
-            _method._data = IntPtr.Zero;
+            _method = default;
             _custom = IntPtr.Zero;
             _custom = IntPtr.Zero;
         }
         }
     }
     }
@@ -275,29 +619,55 @@ namespace Godot.NativeInterop
     // be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
     // be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_array : IDisposable
+    public ref struct godot_array
     {
     {
-        internal unsafe ArrayPrivate* _p;
+        private unsafe ArrayPrivate* _p;
 
 
         [StructLayout(LayoutKind.Sequential)]
         [StructLayout(LayoutKind.Sequential)]
-        internal struct ArrayPrivate
+        private struct ArrayPrivate
         {
         {
             private uint _safeRefCount;
             private uint _safeRefCount;
 
 
-            internal VariantVector _arrayVector;
-            // There's more here, but we don't care as we never store this in C#
+            public VariantVector _arrayVector;
+            // There are more fields here, but we don't care as we never store this in C#
+
+            public readonly int Size
+            {
+                [MethodImpl(MethodImplOptions.AggressiveInlining)]
+                get => _arrayVector.Size;
+            }
         }
         }
 
 
         [StructLayout(LayoutKind.Sequential)]
         [StructLayout(LayoutKind.Sequential)]
-        internal struct VariantVector
+        private struct VariantVector
         {
         {
-            internal IntPtr _writeProxy;
-            internal unsafe godot_variant* _ptr;
+            private IntPtr _writeProxy;
+            public unsafe godot_variant* _ptr;
 
 
-            public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+            public readonly unsafe int Size
+            {
+                [MethodImpl(MethodImplOptions.AggressiveInlining)]
+                get => _ptr != null ? *((int*)_ptr - 1) : 0;
+            }
+        }
+
+        public readonly unsafe godot_variant* Elements
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _p->_arrayVector._ptr;
         }
         }
 
 
-        public unsafe int Size => _p != null ? _p->_arrayVector.Size : 0;
+        public readonly unsafe bool IsAllocated
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _p != null;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _p != null ? _p->Size : 0;
+        }
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -306,6 +676,22 @@ namespace Godot.NativeInterop
             NativeFuncs.godotsharp_array_destroy(ref this);
             NativeFuncs.godotsharp_array_destroy(ref this);
             _p = null;
             _p = null;
         }
         }
+
+        [StructLayout(LayoutKind.Sequential)]
+        // ReSharper disable once InconsistentNaming
+        internal struct movable
+        {
+            private unsafe ArrayPrivate* _p;
+
+            public static unsafe explicit operator movable(in godot_array value)
+                => *(movable*)CustomUnsafe.AsPointer(ref CustomUnsafe.AsRef(value));
+
+            public static unsafe explicit operator godot_array(movable value)
+                => *(godot_array*)Unsafe.AsPointer(ref value);
+
+            public unsafe ref godot_array DangerousSelfRef =>
+                ref CustomUnsafe.AsRef((godot_array*)Unsafe.AsPointer(ref this));
+        }
     }
     }
 
 
     // IMPORTANT:
     // IMPORTANT:
@@ -314,9 +700,15 @@ namespace Godot.NativeInterop
     // be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
     // be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_dictionary : IDisposable
+    public ref struct godot_dictionary
     {
     {
-        internal IntPtr _p;
+        private IntPtr _p;
+
+        public readonly bool IsAllocated
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _p != IntPtr.Zero;
+        }
 
 
         public void Dispose()
         public void Dispose()
         {
         {
@@ -325,14 +717,30 @@ namespace Godot.NativeInterop
             NativeFuncs.godotsharp_dictionary_destroy(ref this);
             NativeFuncs.godotsharp_dictionary_destroy(ref this);
             _p = IntPtr.Zero;
             _p = IntPtr.Zero;
         }
         }
+
+        [StructLayout(LayoutKind.Sequential)]
+        // ReSharper disable once InconsistentNaming
+        internal struct movable
+        {
+            private IntPtr _p;
+
+            public static unsafe explicit operator movable(in godot_dictionary value)
+                => *(movable*)CustomUnsafe.AsPointer(ref CustomUnsafe.AsRef(value));
+
+            public static unsafe explicit operator godot_dictionary(movable value)
+                => *(godot_dictionary*)Unsafe.AsPointer(ref value);
+
+            public unsafe ref godot_dictionary DangerousSelfRef =>
+                ref CustomUnsafe.AsRef((godot_dictionary*)Unsafe.AsPointer(ref this));
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_byte_array : IDisposable
+    public ref struct godot_packed_byte_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe byte* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe byte* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -342,15 +750,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe byte* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_int32_array : IDisposable
+    public ref struct godot_packed_int32_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe int* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe int* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -360,15 +778,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *(_ptr - 1) : 0;
+        public readonly unsafe int* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *(_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_int64_array : IDisposable
+    public ref struct godot_packed_int64_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe long* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe long* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -378,15 +806,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe long* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_float32_array : IDisposable
+    public ref struct godot_packed_float32_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe float* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe float* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -396,15 +834,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe float* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_float64_array : IDisposable
+    public ref struct godot_packed_float64_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe double* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe double* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -414,15 +862,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe double* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_string_array : IDisposable
+    public ref struct godot_packed_string_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe godot_string* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe godot_string* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -432,15 +890,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe godot_string* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_vector2_array : IDisposable
+    public ref struct godot_packed_vector2_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe Vector2* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe Vector2* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -450,15 +918,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe Vector2* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_vector3_array : IDisposable
+    public ref struct godot_packed_vector3_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe Vector3* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe Vector3* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -468,15 +946,25 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe Vector3* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 
 
     [StructLayout(LayoutKind.Sequential)]
     [StructLayout(LayoutKind.Sequential)]
     // ReSharper disable once InconsistentNaming
     // ReSharper disable once InconsistentNaming
-    public struct godot_packed_color_array : IDisposable
+    public ref struct godot_packed_color_array
     {
     {
-        internal IntPtr _writeProxy;
-        internal unsafe Color* _ptr;
+        private IntPtr _writeProxy;
+        private unsafe Color* _ptr;
 
 
         public unsafe void Dispose()
         public unsafe void Dispose()
         {
         {
@@ -486,6 +974,16 @@ namespace Godot.NativeInterop
             _ptr = null;
             _ptr = null;
         }
         }
 
 
-        public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
+        public readonly unsafe Color* Buffer
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr;
+        }
+
+        public readonly unsafe int Size
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => _ptr != null ? *((int*)_ptr - 1) : 0;
+        }
     }
     }
 }
 }

+ 10 - 17
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 using Godot.Bridge;
 using Godot.Bridge;
 
 
@@ -16,22 +15,19 @@ namespace Godot.NativeInterop
                 return null;
                 return null;
 
 
             IntPtr gcHandlePtr;
             IntPtr gcHandlePtr;
-            godot_bool has_cs_script_instance = false.ToGodotBool();
+            godot_bool hasCsScriptInstance;
 
 
             // First try to get the tied managed instance from a CSharpInstance script instance
             // First try to get the tied managed instance from a CSharpInstance script instance
 
 
-            unsafe
-            {
-                gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_get_script_instance_managed(
-                    unmanaged, &has_cs_script_instance);
-            }
+            gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_get_script_instance_managed(
+                unmanaged, out hasCsScriptInstance);
 
 
             if (gcHandlePtr != IntPtr.Zero)
             if (gcHandlePtr != IntPtr.Zero)
                 return (Object)GCHandle.FromIntPtr(gcHandlePtr).Target;
                 return (Object)GCHandle.FromIntPtr(gcHandlePtr).Target;
 
 
             // Otherwise, if the object has a CSharpInstance script instance, return null
             // Otherwise, if the object has a CSharpInstance script instance, return null
 
 
-            if (has_cs_script_instance.ToBool())
+            if (hasCsScriptInstance.ToBool())
                 return null;
                 return null;
 
 
             // If it doesn't have a CSharpInstance script instance, try with native instance bindings
             // If it doesn't have a CSharpInstance script instance, try with native instance bindings
@@ -58,12 +54,9 @@ namespace Godot.NativeInterop
 
 
             if (type == nativeType)
             if (type == nativeType)
             {
             {
-                unsafe
-                {
-                    godot_string_name nativeNameAux = nativeName.NativeValue;
-                    NativeFuncs.godotsharp_internal_tie_native_managed_to_unmanaged(
-                        GCHandle.ToIntPtr(gcHandle), unmanaged, &nativeNameAux, refCounted.ToGodotBool());
-                }
+                var nativeNameSelf = (godot_string_name)nativeName.NativeValue;
+                NativeFuncs.godotsharp_internal_tie_native_managed_to_unmanaged(
+                    GCHandle.ToIntPtr(gcHandle), unmanaged, nativeNameSelf, refCounted.ToGodotBool());
             }
             }
             else
             else
             {
             {
@@ -88,10 +81,10 @@ namespace Godot.NativeInterop
                 GCHandle.ToIntPtr(strongGCHandle), unmanaged);
                 GCHandle.ToIntPtr(strongGCHandle), unmanaged);
         }
         }
 
 
-        public static unsafe Object EngineGetSingleton(string name)
+        public static Object EngineGetSingleton(string name)
         {
         {
-            using godot_string src = Marshaling.mono_string_to_godot(name);
-            return UnmanagedGetManaged(NativeFuncs.godotsharp_engine_get_singleton(&src));
+            using godot_string src = Marshaling.ConvertStringToNative(name);
+            return UnmanagedGetManaged(NativeFuncs.godotsharp_engine_get_singleton(src));
         }
         }
     }
     }
 }
 }

Plik diff jest za duży
+ 252 - 255
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs


+ 196 - 168
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs

@@ -1,15 +1,23 @@
 using System;
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 // ReSharper disable InconsistentNaming
 // ReSharper disable InconsistentNaming
 
 
 namespace Godot.NativeInterop
 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
+    /*
+     * TODO:
+     * P/Invoke pins by-ref parameters in case the managed memory is moved.
+     * That's not needed here since we use "ref structs" which are stack-only.
+     * Unfortunately, the runtime is not smart enough and pins them anyway.
+     * We want to avoid pinning, so we must wrap these DllImports in methods
+     * that reinterpret refs and pointers with CustomUnsafe.AsPointer/AsRef.
+     * I wish such unnecessary boilerplate wasn't needed...
+     */
+
+    [SuppressMessage("Interoperability", "CA1401",
+        MessageId = "P/Invokes should not be visible" /* Meh. What are you gonna do about it? */)]
     public static unsafe partial class NativeFuncs
     public static unsafe partial class NativeFuncs
     {
     {
         private const string GodotDllName = "__Internal";
         private const string GodotDllName = "__Internal";
@@ -17,15 +25,15 @@ namespace Godot.NativeInterop
         // Custom functions
         // Custom functions
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern IntPtr godotsharp_method_bind_get_method(ref godot_string_name p_classname,
+        public static extern IntPtr godotsharp_method_bind_get_method(in godot_string_name p_classname,
             char* p_methodname);
             char* p_methodname);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(
         public static extern delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(
-            ref godot_string_name p_classname);
+            in godot_string_name p_classname);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern IntPtr godotsharp_engine_get_singleton(godot_string* p_name);
+        public static extern IntPtr godotsharp_engine_get_singleton(in godot_string p_name);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         internal static extern void godotsharp_internal_object_disposed(IntPtr ptr);
         internal static extern void godotsharp_internal_object_disposed(IntPtr ptr);
@@ -35,61 +43,64 @@ namespace Godot.NativeInterop
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         internal static extern void godotsharp_internal_object_connect_event_signal(IntPtr obj,
         internal static extern void godotsharp_internal_object_connect_event_signal(IntPtr obj,
-            godot_string_name* eventSignal);
+            in godot_string_name eventSignal);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         internal static extern Error godotsharp_internal_signal_awaiter_connect(IntPtr source,
         internal static extern Error godotsharp_internal_signal_awaiter_connect(IntPtr source,
-            ref godot_string_name signal,
+            in godot_string_name signal,
             IntPtr target, IntPtr awaiterHandlePtr);
             IntPtr target, IntPtr awaiterHandlePtr);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_internal_tie_native_managed_to_unmanaged(IntPtr gcHandleIntPtr,
-            IntPtr unmanaged, godot_string_name* nativeName, godot_bool refCounted);
+        internal static extern void godotsharp_internal_tie_native_managed_to_unmanaged(IntPtr gcHandleIntPtr,
+            IntPtr unmanaged, in godot_string_name nativeName, godot_bool refCounted);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_internal_tie_user_managed_to_unmanaged(IntPtr gcHandleIntPtr,
+        internal static extern void godotsharp_internal_tie_user_managed_to_unmanaged(IntPtr gcHandleIntPtr,
             IntPtr unmanaged, IntPtr scriptPtr, godot_bool refCounted);
             IntPtr unmanaged, IntPtr scriptPtr, godot_bool refCounted);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup(
+        internal static extern void godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup(
             IntPtr gcHandleIntPtr, IntPtr unmanaged);
             IntPtr gcHandleIntPtr, IntPtr unmanaged);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern IntPtr godotsharp_internal_unmanaged_get_script_instance_managed(IntPtr p_unmanaged,
-            godot_bool* r_has_cs_script_instance);
+        internal static extern IntPtr godotsharp_internal_unmanaged_get_script_instance_managed(IntPtr p_unmanaged,
+            out godot_bool r_has_cs_script_instance);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern IntPtr godotsharp_internal_unmanaged_get_instance_binding_managed(IntPtr p_unmanaged);
+        internal static extern IntPtr godotsharp_internal_unmanaged_get_instance_binding_managed(IntPtr p_unmanaged);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern IntPtr godotsharp_internal_unmanaged_instance_binding_create_managed(IntPtr p_unmanaged,
+        internal static extern IntPtr godotsharp_internal_unmanaged_instance_binding_create_managed(IntPtr p_unmanaged,
             IntPtr oldGCHandlePtr);
             IntPtr oldGCHandlePtr);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern IntPtr godotsharp_internal_new_csharp_script();
+        internal static extern IntPtr godotsharp_internal_new_csharp_script();
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_array_filter_godot_objects_by_native(godot_string_name* p_native_name,
-            godot_array* p_input, godot_array* r_output);
+        internal static extern void godotsharp_array_filter_godot_objects_by_native(in godot_string_name p_native_name,
+            in godot_array p_input, out godot_array r_output);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_array_filter_godot_objects_by_non_native(godot_array* p_input,
-            godot_array* r_output);
+        internal static extern void godotsharp_array_filter_godot_objects_by_non_native(in godot_array p_input,
+            out godot_array r_output);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void godotsharp_ref_destroy(ref godot_ref p_instance);
         public static extern void godotsharp_ref_destroy(ref godot_ref p_instance);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_name_new_from_string(godot_string_name* dest, godot_string* name);
+        public static extern void godotsharp_string_name_new_from_string(out godot_string_name r_dest,
+            in godot_string p_name);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_new_from_string(godot_node_path* dest, godot_string* name);
+        public static extern void godotsharp_node_path_new_from_string(out godot_node_path r_dest,
+            in godot_string p_name);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_name_as_string(godot_string* r_dest, godot_string_name* p_name);
+        public static extern void
+            godotsharp_string_name_as_string(out godot_string r_dest, in godot_string_name p_name);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_as_string(godot_string* r_dest, godot_node_path* p_np);
+        public static extern void godotsharp_node_path_as_string(out godot_string r_dest, in godot_node_path p_np);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src,
         public static extern godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src,
@@ -124,16 +135,24 @@ namespace Godot.NativeInterop
             int p_length);
             int p_length);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_packed_string_array_add(godot_packed_string_array* r_dest,
-            godot_string* p_element);
+        public static extern void godotsharp_packed_string_array_add(ref godot_packed_string_array r_dest,
+            in godot_string p_element);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle,
         public static extern void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle,
-            godot_callable* r_callable);
+            out godot_callable r_callable);
+
+        [DllImport(GodotDllName)]
+        internal static extern godot_bool godotsharp_callable_get_data_for_marshalling(in godot_callable p_callable,
+            out IntPtr r_delegate_handle, out IntPtr r_object, out godot_string_name r_name);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_bool godotsharp_callable_get_data_for_marshalling(godot_callable* p_callable,
-            IntPtr* r_delegate_handle, IntPtr* r_object, godot_string_name* r_name);
+        internal static extern godot_variant godotsharp_callable_call(in godot_callable p_callable,
+            godot_variant** p_args, int p_arg_count, out godot_variant_call_error p_call_error);
+
+        [DllImport(GodotDllName)]
+        internal static extern void godotsharp_callable_call_deferred(in godot_callable p_callable,
+            godot_variant** p_args, int p_arg_count);
 
 
         // GDNative functions
         // GDNative functions
 
 
@@ -145,219 +164,223 @@ namespace Godot.NativeInterop
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_variant godotsharp_method_bind_call(IntPtr p_method_bind, IntPtr p_instance,
         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);
+            godot_variant** p_args, int p_arg_count, out godot_variant_call_error p_call_error);
 
 
         // variant.h
         // variant.h
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_string_name(godot_variant* r_dest, godot_string_name* p_s);
+        public static extern void
+            godotsharp_variant_new_string_name(out godot_variant r_dest, in godot_string_name p_s);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_node_path(godot_variant* r_dest, godot_node_path* p_np);
+        public static extern void godotsharp_variant_new_node_path(out godot_variant r_dest, in godot_node_path p_np);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_object(godot_variant* r_dest, IntPtr p_obj);
+        public static extern void godotsharp_variant_new_object(out godot_variant r_dest, IntPtr p_obj);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_transform2d(godot_variant* r_dest, Transform2D* p_t2d);
+        public static extern void godotsharp_variant_new_transform2d(out godot_variant r_dest, in Transform2D p_t2d);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_vector4(godot_variant* r_dest, Vector4* p_vec4);
+        public static extern void godotsharp_variant_new_vector4(out godot_variant r_dest, in Vector4 p_vec4);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_vector4i(godot_variant* r_dest, Vector4i* p_vec4i);
+        public static extern void godotsharp_variant_new_vector4i(out godot_variant r_dest, in Vector4i p_vec4i);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_basis(godot_variant* r_dest, Basis* p_basis);
+        public static extern void godotsharp_variant_new_basis(out godot_variant r_dest, in Basis p_basis);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_transform3d(godot_variant* r_dest, Transform3D* p_trans);
+        public static extern void godotsharp_variant_new_transform3d(out godot_variant r_dest, in Transform3D p_trans);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_projection(godot_variant* r_dest, Projection* p_proj);
+        public static extern void godotsharp_variant_new_projection(out godot_variant r_dest, in Projection p_proj);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_aabb(godot_variant* r_dest, AABB* p_aabb);
+        public static extern void godotsharp_variant_new_aabb(out godot_variant r_dest, in AABB p_aabb);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_dictionary(godot_variant* r_dest, godot_dictionary* p_dict);
+        public static extern void godotsharp_variant_new_dictionary(out godot_variant r_dest,
+            in godot_dictionary p_dict);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_array(godot_variant* r_dest, godot_array* p_arr);
+        public static extern void godotsharp_variant_new_array(out godot_variant r_dest, in godot_array p_arr);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_byte_array(godot_variant* r_dest,
-            godot_packed_byte_array* p_pba);
+        public static extern void godotsharp_variant_new_packed_byte_array(out godot_variant r_dest,
+            in godot_packed_byte_array p_pba);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_int32_array(godot_variant* r_dest,
-            godot_packed_int32_array* p_pia);
+        public static extern void godotsharp_variant_new_packed_int32_array(out godot_variant r_dest,
+            in godot_packed_int32_array p_pia);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_int64_array(godot_variant* r_dest,
-            godot_packed_int64_array* p_pia);
+        public static extern void godotsharp_variant_new_packed_int64_array(out godot_variant r_dest,
+            in godot_packed_int64_array p_pia);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_float32_array(godot_variant* r_dest,
-            godot_packed_float32_array* p_pra);
+        public static extern void godotsharp_variant_new_packed_float32_array(out godot_variant r_dest,
+            in godot_packed_float32_array p_pra);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_float64_array(godot_variant* r_dest,
-            godot_packed_float64_array* p_pra);
+        public static extern void godotsharp_variant_new_packed_float64_array(out godot_variant r_dest,
+            in godot_packed_float64_array p_pra);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_string_array(godot_variant* r_dest,
-            godot_packed_string_array* p_psa);
+        public static extern void godotsharp_variant_new_packed_string_array(out godot_variant r_dest,
+            in godot_packed_string_array p_psa);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_vector2_array(godot_variant* r_dest,
-            godot_packed_vector2_array* p_pv2a);
+        public static extern void godotsharp_variant_new_packed_vector2_array(out godot_variant r_dest,
+            in godot_packed_vector2_array p_pv2a);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_vector3_array(godot_variant* r_dest,
-            godot_packed_vector3_array* p_pv3a);
+        public static extern void godotsharp_variant_new_packed_vector3_array(out godot_variant r_dest,
+            in godot_packed_vector3_array p_pv3a);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_variant_new_packed_color_array(godot_variant* r_dest,
-            godot_packed_color_array* p_pca);
+        public static extern void godotsharp_variant_new_packed_color_array(out godot_variant r_dest,
+            in godot_packed_color_array p_pca);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_bool godotsharp_variant_as_bool(godot_variant* p_self);
+        public static extern godot_bool godotsharp_variant_as_bool(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Int64 godotsharp_variant_as_int(godot_variant* p_self);
+        public static extern Int64 godotsharp_variant_as_int(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern double godotsharp_variant_as_float(godot_variant* p_self);
+        public static extern double godotsharp_variant_as_float(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_string godotsharp_variant_as_string(godot_variant* p_self);
+        public static extern godot_string godotsharp_variant_as_string(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Vector2 godotsharp_variant_as_vector2(godot_variant* p_self);
+        public static extern Vector2 godotsharp_variant_as_vector2(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Vector2i godotsharp_variant_as_vector2i(godot_variant* p_self);
+        public static extern Vector2i godotsharp_variant_as_vector2i(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Rect2 godotsharp_variant_as_rect2(godot_variant* p_self);
+        public static extern Rect2 godotsharp_variant_as_rect2(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Rect2i godotsharp_variant_as_rect2i(godot_variant* p_self);
+        public static extern Rect2i godotsharp_variant_as_rect2i(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Vector3 godotsharp_variant_as_vector3(godot_variant* p_self);
+        public static extern Vector3 godotsharp_variant_as_vector3(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Vector3i godotsharp_variant_as_vector3i(godot_variant* p_self);
+        public static extern Vector3i godotsharp_variant_as_vector3i(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Transform2D godotsharp_variant_as_transform2d(godot_variant* p_self);
+        public static extern Transform2D godotsharp_variant_as_transform2d(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Vector4 godotsharp_variant_as_vector4(godot_variant* p_self);
+        public static extern Vector4 godotsharp_variant_as_vector4(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Vector4i godotsharp_variant_as_vector4i(godot_variant* p_self);
+        public static extern Vector4i godotsharp_variant_as_vector4i(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Plane godotsharp_variant_as_plane(godot_variant* p_self);
+        public static extern Plane godotsharp_variant_as_plane(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Quaternion godotsharp_variant_as_quaternion(godot_variant* p_self);
+        public static extern Quaternion godotsharp_variant_as_quaternion(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern AABB godotsharp_variant_as_aabb(godot_variant* p_self);
+        public static extern AABB godotsharp_variant_as_aabb(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Basis godotsharp_variant_as_basis(godot_variant* p_self);
+        public static extern Basis godotsharp_variant_as_basis(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Transform3D godotsharp_variant_as_transform3d(godot_variant* p_self);
+        public static extern Transform3D godotsharp_variant_as_transform3d(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Projection godotsharp_variant_as_projection(godot_variant* p_self);
+        public static extern Projection godotsharp_variant_as_projection(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern Color godotsharp_variant_as_color(godot_variant* p_self);
+        public static extern Color godotsharp_variant_as_color(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_string_name godotsharp_variant_as_string_name(godot_variant* p_self);
+        public static extern godot_string_name godotsharp_variant_as_string_name(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_node_path godotsharp_variant_as_node_path(godot_variant* p_self);
+        public static extern godot_node_path godotsharp_variant_as_node_path(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern RID godotsharp_variant_as_rid(godot_variant* p_self);
+        public static extern RID godotsharp_variant_as_rid(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_callable godotsharp_variant_as_callable(godot_variant* p_self);
+        public static extern godot_callable godotsharp_variant_as_callable(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_signal godotsharp_variant_as_signal(godot_variant* p_self);
+        public static extern godot_signal godotsharp_variant_as_signal(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_dictionary godotsharp_variant_as_dictionary(godot_variant* p_self);
+        public static extern godot_dictionary godotsharp_variant_as_dictionary(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_array godotsharp_variant_as_array(godot_variant* p_self);
+        public static extern godot_array godotsharp_variant_as_array(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_packed_byte_array godotsharp_variant_as_packed_byte_array(godot_variant* p_self);
+        public static extern godot_packed_byte_array godotsharp_variant_as_packed_byte_array(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_packed_int32_array godotsharp_variant_as_packed_int32_array(godot_variant* p_self);
+        public static extern godot_packed_int32_array godotsharp_variant_as_packed_int32_array(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_packed_int64_array godotsharp_variant_as_packed_int64_array(godot_variant* p_self);
+        public static extern godot_packed_int64_array godotsharp_variant_as_packed_int64_array(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_packed_float32_array godotsharp_variant_as_packed_float32_array(
         public static extern godot_packed_float32_array godotsharp_variant_as_packed_float32_array(
-            godot_variant* p_self);
+            in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_packed_float64_array godotsharp_variant_as_packed_float64_array(
         public static extern godot_packed_float64_array godotsharp_variant_as_packed_float64_array(
-            godot_variant* p_self);
+            in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_packed_string_array godotsharp_variant_as_packed_string_array(godot_variant* p_self);
+        public static extern godot_packed_string_array godotsharp_variant_as_packed_string_array(
+            in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(
         public static extern godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(
-            godot_variant* p_self);
+            in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(
         public static extern godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(
-            godot_variant* p_self);
+            in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_packed_color_array godotsharp_variant_as_packed_color_array(godot_variant* p_self);
+        public static extern godot_packed_color_array godotsharp_variant_as_packed_color_array(in godot_variant p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_bool godotsharp_variant_equals(godot_variant* p_a, godot_variant* p_b);
+        public static extern godot_bool godotsharp_variant_equals(in godot_variant p_a, in godot_variant p_b);
 
 
         // string.h
         // string.h
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_new_with_utf16_chars(godot_string* r_dest, char* p_contents);
+        public static extern void godotsharp_string_new_with_utf16_chars(out godot_string r_dest, char* p_contents);
 
 
         // string_name.h
         // string_name.h
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_name_new_copy(godot_string_name* r_dest, godot_string_name* p_src);
+        public static extern void godotsharp_string_name_new_copy(out godot_string_name r_dest,
+            in godot_string_name p_src);
 
 
         // node_path.h
         // node_path.h
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_new_copy(godot_node_path* r_dest, godot_node_path* p_src);
+        public static extern void godotsharp_node_path_new_copy(out godot_node_path r_dest, in godot_node_path p_src);
 
 
         // array.h
         // array.h
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_array_new(godot_array* p_self);
+        public static extern void godotsharp_array_new(out godot_array r_dest);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_array_new_copy(godot_array* r_dest, godot_array* p_src);
+        public static extern void godotsharp_array_new_copy(out godot_array r_dest, in godot_array p_src);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_variant* godotsharp_array_ptrw(ref godot_array p_self);
         public static extern godot_variant* godotsharp_array_ptrw(ref godot_array p_self);
@@ -365,10 +388,11 @@ namespace Godot.NativeInterop
         // dictionary.h
         // dictionary.h
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_dictionary_new(godot_dictionary* p_self);
+        public static extern void godotsharp_dictionary_new(out godot_dictionary r_dest);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_dictionary_new_copy(godot_dictionary* r_dest, godot_dictionary* p_src);
+        public static extern void godotsharp_dictionary_new_copy(out godot_dictionary r_dest,
+            in godot_dictionary p_src);
 
 
         // destroy functions
         // destroy functions
 
 
@@ -426,17 +450,17 @@ namespace Godot.NativeInterop
         // Array
         // Array
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_array_add(ref godot_array p_self, godot_variant* p_item);
+        public static extern int godotsharp_array_add(ref godot_array p_self, in godot_variant p_item);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void
         public static extern void
             godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
             godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_array_index_of(ref godot_array p_self, godot_variant* p_item);
+        public static extern int godotsharp_array_index_of(ref godot_array p_self, in godot_variant p_item);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_array_insert(ref godot_array p_self, int p_index, godot_variant* p_item);
+        public static extern void godotsharp_array_insert(ref godot_array p_self, int p_index, in godot_variant p_item);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void godotsharp_array_remove_at(ref godot_array p_self, int p_index);
         public static extern void godotsharp_array_remove_at(ref godot_array p_self, int p_index);
@@ -448,18 +472,18 @@ namespace Godot.NativeInterop
         public static extern Error godotsharp_array_shuffle(ref godot_array p_self);
         public static extern Error godotsharp_array_shuffle(ref godot_array p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_array_to_string(ref godot_array p_self, godot_string* r_str);
+        public static extern void godotsharp_array_to_string(ref godot_array p_self, out godot_string r_str);
 
 
         // Dictionary
         // Dictionary
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_bool godotsharp_dictionary_try_get_value(ref godot_dictionary p_self,
         public static extern godot_bool godotsharp_dictionary_try_get_value(ref godot_dictionary p_self,
-            godot_variant* p_key,
+            in godot_variant p_key,
             out godot_variant r_value);
             out godot_variant r_value);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_dictionary_set_value(ref godot_dictionary p_self, godot_variant* p_key,
-            godot_variant* p_value);
+        public static extern void godotsharp_dictionary_set_value(ref godot_dictionary p_self, in godot_variant p_key,
+            in godot_variant p_value);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void godotsharp_dictionary_keys(ref godot_dictionary p_self, out godot_array r_dest);
         public static extern void godotsharp_dictionary_keys(ref godot_dictionary p_self, out godot_array r_dest);
@@ -475,15 +499,15 @@ namespace Godot.NativeInterop
             out godot_variant r_key, out godot_variant r_value);
             out godot_variant r_key, out godot_variant r_value);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_dictionary_add(ref godot_dictionary p_self, godot_variant* p_key,
-            godot_variant* p_value);
+        public static extern void godotsharp_dictionary_add(ref godot_dictionary p_self, in godot_variant p_key,
+            in godot_variant p_value);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void godotsharp_dictionary_clear(ref godot_dictionary p_self);
         public static extern void godotsharp_dictionary_clear(ref godot_dictionary p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_bool godotsharp_dictionary_contains_key(ref godot_dictionary p_self,
         public static extern godot_bool godotsharp_dictionary_contains_key(ref godot_dictionary p_self,
-            godot_variant* p_key);
+            in godot_variant p_key);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep,
         public static extern void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep,
@@ -491,149 +515,153 @@ namespace Godot.NativeInterop
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern godot_bool godotsharp_dictionary_remove_key(ref godot_dictionary p_self,
         public static extern godot_bool godotsharp_dictionary_remove_key(ref godot_dictionary p_self,
-            godot_variant* p_key);
+            in godot_variant p_key);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_dictionary_to_string(ref godot_dictionary p_self, godot_string* r_str);
+        public static extern void godotsharp_dictionary_to_string(ref godot_dictionary p_self, out godot_string r_str);
 
 
         // StringExtensions
         // StringExtensions
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_md5_buffer(godot_string* p_self,
-            godot_packed_byte_array* r_md5_buffer);
+        public static extern void godotsharp_string_md5_buffer(in godot_string p_self,
+            out godot_packed_byte_array r_md5_buffer);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_md5_text(godot_string* p_self, godot_string* r_md5_text);
+        public static extern void godotsharp_string_md5_text(in godot_string p_self, out godot_string r_md5_text);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_string_rfind(godot_string* p_self, godot_string* p_what, int p_from);
+        public static extern int godotsharp_string_rfind(in godot_string p_self, in godot_string p_what, int p_from);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_string_rfindn(godot_string* p_self, godot_string* p_what, int p_from);
+        public static extern int godotsharp_string_rfindn(in godot_string p_self, in godot_string p_what, int p_from);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_sha256_buffer(godot_string* p_self,
-            godot_packed_byte_array* r_sha256_buffer);
+        public static extern void godotsharp_string_sha256_buffer(in godot_string p_self,
+            out godot_packed_byte_array r_sha256_buffer);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_sha256_text(godot_string* p_self, godot_string* r_sha256_text);
+        public static extern void godotsharp_string_sha256_text(in godot_string p_self,
+            out godot_string r_sha256_text);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_string_simplify_path(godot_string* p_self, godot_string* r_simplified_path);
+        public static extern void godotsharp_string_simplify_path(in godot_string p_self,
+            out godot_string r_simplified_path);
 
 
         // NodePath
         // NodePath
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_get_as_property_path(ref godot_node_path p_self,
+        public static extern void godotsharp_node_path_get_as_property_path(in godot_node_path p_self,
             ref godot_node_path r_dest);
             ref godot_node_path r_dest);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_get_concatenated_names(ref godot_node_path p_self,
-            godot_string* r_names);
+        public static extern void godotsharp_node_path_get_concatenated_names(in godot_node_path p_self,
+            out godot_string r_names);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_get_concatenated_subnames(ref godot_node_path p_self,
-            godot_string* r_subnames);
+        public static extern void godotsharp_node_path_get_concatenated_subnames(in godot_node_path p_self,
+            out godot_string r_subnames);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_get_name(ref godot_node_path p_self, int p_idx,
-            godot_string* r_name);
+        public static extern void godotsharp_node_path_get_name(in godot_node_path p_self, int p_idx,
+            out godot_string r_name);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_node_path_get_name_count(ref godot_node_path p_self);
+        public static extern int godotsharp_node_path_get_name_count(in godot_node_path p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_node_path_get_subname(ref godot_node_path p_self, int p_idx,
-            godot_string* r_subname);
+        public static extern void godotsharp_node_path_get_subname(in godot_node_path p_self, int p_idx,
+            out godot_string r_subname);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_node_path_get_subname_count(ref godot_node_path p_self);
+        public static extern int godotsharp_node_path_get_subname_count(in godot_node_path p_self);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern godot_bool godotsharp_node_path_is_absolute(ref godot_node_path p_self);
+        public static extern godot_bool godotsharp_node_path_is_absolute(in godot_node_path p_self);
 
 
         // GD, etc
         // GD, etc
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_bytes2var(godot_packed_byte_array* p_bytes, godot_bool p_allow_objects,
-            godot_variant* r_ret);
+        internal static extern void godotsharp_bytes2var(in godot_packed_byte_array p_bytes,
+            godot_bool p_allow_objects,
+            out godot_variant r_ret);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_convert(godot_variant* p_what, int p_type, godot_variant* r_ret);
+        internal static extern void godotsharp_convert(in godot_variant p_what, int p_type,
+            out godot_variant r_ret);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_hash(godot_variant* var);
+        internal static extern int godotsharp_hash(in godot_variant p_var);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern IntPtr godotsharp_instance_from_id(ulong instanceId);
+        internal static extern IntPtr godotsharp_instance_from_id(ulong p_instance_id);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_print(godot_string* p_what);
+        internal static extern void godotsharp_print(in godot_string p_what);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_print_rich(godot_string* p_what);
+        public static extern void godotsharp_print_rich(in godot_string p_what);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_printerr(godot_string* p_what);
+        internal static extern void godotsharp_printerr(in godot_string p_what);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_printraw(godot_string* p_what);
+        internal static extern void godotsharp_printraw(in godot_string p_what);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_prints(godot_string* p_what);
+        internal static extern void godotsharp_prints(in godot_string p_what);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_printt(godot_string* p_what);
+        internal static extern void godotsharp_printt(in godot_string p_what);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern float godotsharp_randf();
+        internal static extern float godotsharp_randf();
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern uint godotsharp_randi();
+        internal static extern uint godotsharp_randi();
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_randomize();
+        internal static extern void godotsharp_randomize();
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern double godotsharp_randf_range(double from, double to);
+        internal static extern double godotsharp_randf_range(double from, double to);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern double godotsharp_randfn(double mean, double deviation);
+        internal static extern double godotsharp_randfn(double mean, double deviation);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern int godotsharp_randi_range(int from, int to);
+        internal static extern int godotsharp_randi_range(int from, int to);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern uint godotsharp_rand_from_seed(ulong seed, out ulong newSeed);
+        internal static extern uint godotsharp_rand_from_seed(ulong seed, out ulong newSeed);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_seed(ulong seed);
+        internal static extern void godotsharp_seed(ulong seed);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_weakref(IntPtr obj, godot_ref* r_weak_ref);
+        internal static extern void godotsharp_weakref(IntPtr p_obj, out godot_ref r_weak_ref);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern string godotsharp_str(godot_array* p_what, godot_string* r_ret);
+        internal static extern void godotsharp_str(in godot_array p_what, out godot_string r_ret);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_str2var(godot_string* p_str, godot_variant* r_ret);
+        internal static extern void godotsharp_str2var(in godot_string p_str, out godot_variant r_ret);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_var2bytes(godot_variant* what, godot_bool fullObjects,
-            godot_packed_byte_array* bytes);
+        internal static extern void godotsharp_var2bytes(in godot_variant p_what, godot_bool p_full_objects,
+            out godot_packed_byte_array r_bytes);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_var2str(godot_variant* var, godot_string* r_ret);
+        internal static extern void godotsharp_var2str(in godot_variant p_var, out godot_string r_ret);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_pusherror(godot_string* type);
+        internal static extern void godotsharp_pusherror(in godot_string p_str);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_pushwarning(godot_string* type);
+        internal static extern void godotsharp_pushwarning(in godot_string p_str);
 
 
         // Object
         // Object
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern string godotsharp_object_to_string(IntPtr ptr, godot_string* r_str);
+        public static extern void godotsharp_object_to_string(IntPtr ptr, out godot_string r_str);
     }
     }
 }
 }

+ 19 - 42
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs

@@ -1,83 +1,60 @@
-using System;
-using System.Runtime.CompilerServices;
-
 // ReSharper disable InconsistentNaming
 // ReSharper disable InconsistentNaming
 
 
 namespace Godot.NativeInterop
 namespace Godot.NativeInterop
 {
 {
-    public static unsafe partial class NativeFuncs
+    public static partial class NativeFuncs
     {
     {
-        public static godot_string_name godotsharp_string_name_new_copy(godot_string_name* src)
+        public static godot_string_name godotsharp_string_name_new_copy(in godot_string_name src)
         {
         {
-            godot_string_name ret;
-            godotsharp_string_name_new_copy(&ret, src);
+            if (src.IsEmpty)
+                return default;
+            godotsharp_string_name_new_copy(out godot_string_name ret, src);
             return ret;
             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)
+        public static godot_node_path godotsharp_node_path_new_copy(in godot_node_path src)
         {
         {
-            godot_node_path ret;
-            godotsharp_node_path_new_copy(&ret, src);
+            if (src.IsEmpty)
+                return default;
+            godotsharp_node_path_new_copy(out godot_node_path ret, src);
             return ret;
             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()
         public static godot_array godotsharp_array_new()
         {
         {
-            godot_array ret;
-            godotsharp_array_new(&ret);
+            godotsharp_array_new(out godot_array ret);
             return ret;
             return ret;
         }
         }
 
 
-        public static godot_array godotsharp_array_new_copy(godot_array* src)
+        public static godot_array godotsharp_array_new_copy(in godot_array src)
         {
         {
-            godot_array ret;
-            godotsharp_array_new_copy(&ret, src);
+            godotsharp_array_new_copy(out godot_array ret, src);
             return ret;
             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()
         public static godot_dictionary godotsharp_dictionary_new()
         {
         {
-            godot_dictionary ret;
-            godotsharp_dictionary_new(&ret);
+            godotsharp_dictionary_new(out godot_dictionary ret);
             return ret;
             return ret;
         }
         }
 
 
-        public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary* src)
+        public static godot_dictionary godotsharp_dictionary_new_copy(in godot_dictionary src)
         {
         {
-            godot_dictionary ret;
-            godotsharp_dictionary_new_copy(&ret, src);
+            godotsharp_dictionary_new_copy(out godot_dictionary ret, src);
             return ret;
             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)
         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);
+            using godot_string src = Marshaling.ConvertStringToNative(name);
+            godotsharp_string_name_new_from_string(out godot_string_name ret, src);
             return ret;
             return ret;
         }
         }
 
 
         public static godot_node_path godotsharp_node_path_new_from_string(string name)
         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);
+            using godot_string src = Marshaling.ConvertStringToNative(name);
+            godotsharp_node_path_new_from_string(out godot_node_path ret, src);
             return ret;
             return ret;
         }
         }
     }
     }

+ 20 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeVariantPtrArgs.cs

@@ -0,0 +1,20 @@
+using System.Runtime.CompilerServices;
+
+namespace Godot.NativeInterop
+{
+    // Our source generators will add trampolines methods that access variant arguments.
+    // This struct makes that possible without having to enable `AllowUnsafeBlocks` in game projects.
+
+    public unsafe ref struct NativeVariantPtrArgs
+    {
+        private godot_variant** _args;
+
+        internal NativeVariantPtrArgs(godot_variant** args) => _args = args;
+
+        public ref godot_variant this[int index]
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get => ref *_args[index];
+        }
+    }
+}

+ 5 - 5
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantSpanHelpers.cs

@@ -2,13 +2,13 @@ using System;
 
 
 namespace Godot.NativeInterop
 namespace Godot.NativeInterop
 {
 {
-    internal ref struct VariantSpanDisposer
+    internal readonly ref struct VariantSpanDisposer
     {
     {
-        private readonly Span<godot_variant> _variantSpan;
+        private readonly Span<godot_variant.movable> _variantSpan;
 
 
         // IMPORTANT: The span element must be default initialized.
         // IMPORTANT: The span element must be default initialized.
         // Make sure call Clear() on the span if it was created with stackalloc.
         // Make sure call Clear() on the span if it was created with stackalloc.
-        public VariantSpanDisposer(Span<godot_variant> variantSpan)
+        public VariantSpanDisposer(Span<godot_variant.movable> variantSpan)
         {
         {
             _variantSpan = variantSpan;
             _variantSpan = variantSpan;
         }
         }
@@ -16,7 +16,7 @@ namespace Godot.NativeInterop
         public void Dispose()
         public void Dispose()
         {
         {
             for (int i = 0; i < _variantSpan.Length; i++)
             for (int i = 0; i < _variantSpan.Length; i++)
-                _variantSpan[i].Dispose();
+                _variantSpan[i].DangerousSelfRef.Dispose();
         }
         }
     }
     }
 
 
@@ -24,7 +24,7 @@ namespace Godot.NativeInterop
     {
     {
         // Used to make sure we always initialize the span values to the default,
         // 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.
         // as we need that in order to safely dispose all elements after.
-        public static Span<godot_variant> Cleared(this Span<godot_variant> span)
+        public static Span<godot_variant.movable> Cleared(this Span<godot_variant.movable> span)
         {
         {
             span.Clear();
             span.Clear();
             return span;
             return span;

+ 162 - 188
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Runtime.CompilerServices;
 
 
 // ReSharper disable InconsistentNaming
 // ReSharper disable InconsistentNaming
 
 
@@ -8,378 +7,353 @@ namespace Godot.NativeInterop
     public static class VariantUtils
     public static class VariantUtils
     {
     {
         public static godot_variant CreateFromRID(RID from)
         public static godot_variant CreateFromRID(RID from)
-            => new() { _type = Variant.Type.Rid, _data = { _m_rid = from } };
+            => new() { Type = Variant.Type.Rid, RID = from };
 
 
         public static godot_variant CreateFromBool(bool from)
         public static godot_variant CreateFromBool(bool from)
-            => new() { _type = Variant.Type.Bool, _data = { _bool = from.ToGodotBool() } };
+            => new() { Type = Variant.Type.Bool, Bool = from.ToGodotBool() };
 
 
         public static godot_variant CreateFromInt(long from)
         public static godot_variant CreateFromInt(long from)
-            => new() { _type = Variant.Type.Int, _data = { _int = from } };
+            => new() { Type = Variant.Type.Int, Int = from };
 
 
         public static godot_variant CreateFromInt(ulong from)
         public static godot_variant CreateFromInt(ulong from)
-            => new() { _type = Variant.Type.Int, _data = { _int = (long)from } };
+            => new() { Type = Variant.Type.Int, Int = (long)from };
 
 
         public static godot_variant CreateFromFloat(double from)
         public static godot_variant CreateFromFloat(double from)
-            => new() { _type = Variant.Type.Float, _data = { _float = from } };
+            => new() { Type = Variant.Type.Float, Float = from };
 
 
         public static godot_variant CreateFromVector2(Vector2 from)
         public static godot_variant CreateFromVector2(Vector2 from)
-            => new() { _type = Variant.Type.Vector2, _data = { _m_vector2 = from } };
+            => new() { Type = Variant.Type.Vector2, Vector2 = from };
 
 
         public static godot_variant CreateFromVector2i(Vector2i from)
         public static godot_variant CreateFromVector2i(Vector2i from)
-            => new() { _type = Variant.Type.Vector2i, _data = { _m_vector2i = from } };
+            => new() { Type = Variant.Type.Vector2i, Vector2i = from };
 
 
         public static godot_variant CreateFromVector3(Vector3 from)
         public static godot_variant CreateFromVector3(Vector3 from)
-            => new() { _type = Variant.Type.Vector3, _data = { _m_vector3 = from } };
+            => new() { Type = Variant.Type.Vector3, Vector3 = from };
 
 
         public static godot_variant CreateFromVector3i(Vector3i from)
         public static godot_variant CreateFromVector3i(Vector3i from)
-            => new() { _type = Variant.Type.Vector3i, _data = { _m_vector3i = from } };
+            => new() { Type = Variant.Type.Vector3i, Vector3i = from };
 
 
         public static godot_variant CreateFromRect2(Rect2 from)
         public static godot_variant CreateFromRect2(Rect2 from)
-            => new() { _type = Variant.Type.Rect2, _data = { _m_rect2 = from } };
+            => new() { Type = Variant.Type.Rect2, Rect2 = from };
 
 
         public static godot_variant CreateFromRect2i(Rect2i from)
         public static godot_variant CreateFromRect2i(Rect2i from)
-            => new() { _type = Variant.Type.Rect2i, _data = { _m_rect2i = from } };
+            => new() { Type = Variant.Type.Rect2i, Rect2i = from };
 
 
         public static godot_variant CreateFromQuaternion(Quaternion from)
         public static godot_variant CreateFromQuaternion(Quaternion from)
-            => new() { _type = Variant.Type.Quaternion, _data = { _m_quaternion = from } };
+            => new() { Type = Variant.Type.Quaternion, Quaternion = from };
 
 
         public static godot_variant CreateFromColor(Color from)
         public static godot_variant CreateFromColor(Color from)
-            => new() { _type = Variant.Type.Color, _data = { _m_color = from } };
+            => new() { Type = Variant.Type.Color, Color = from };
 
 
         public static godot_variant CreateFromPlane(Plane from)
         public static godot_variant CreateFromPlane(Plane from)
-            => new() { _type = Variant.Type.Plane, _data = { _m_plane = from } };
+            => new() { Type = Variant.Type.Plane, Plane = from };
 
 
-        public static unsafe godot_variant CreateFromTransform2D(Transform2D from)
+        public static godot_variant CreateFromTransform2D(Transform2D from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_transform2d(&ret, &from);
+            NativeFuncs.godotsharp_variant_new_transform2d(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromVector4(Vector4 from)
+        public static godot_variant CreateFromVector4(Vector4 from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_vector4(&ret, &from);
+            NativeFuncs.godotsharp_variant_new_vector4(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromVector4i(Vector4i from)
+        public static godot_variant CreateFromVector4i(Vector4i from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_vector4i(&ret, &from);
+            NativeFuncs.godotsharp_variant_new_vector4i(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromBasis(Basis from)
+        public static godot_variant CreateFromBasis(Basis from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_basis(&ret, &from);
+            NativeFuncs.godotsharp_variant_new_basis(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromTransform3D(Transform3D from)
+        public static godot_variant CreateFromTransform3D(Transform3D from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_transform3d(&ret, &from);
+            NativeFuncs.godotsharp_variant_new_transform3d(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromProjection(Projection from)
+        public static godot_variant CreateFromProjection(Projection from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_projection(&ret, &from);
+            NativeFuncs.godotsharp_variant_new_projection(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromAABB(AABB from)
+        public static godot_variant CreateFromAABB(AABB from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_aabb(&ret, &from);
+            NativeFuncs.godotsharp_variant_new_aabb(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
         // Explicit name to make it very clear
         // Explicit name to make it very clear
         public static godot_variant CreateFromCallableTakingOwnershipOfDisposableValue(godot_callable from)
         public static godot_variant CreateFromCallableTakingOwnershipOfDisposableValue(godot_callable from)
-            => new() { _type = Variant.Type.Callable, _data = { _m_callable = from } };
+            => new() { Type = Variant.Type.Callable, Callable = from };
 
 
         // Explicit name to make it very clear
         // Explicit name to make it very clear
         public static godot_variant CreateFromSignalTakingOwnershipOfDisposableValue(godot_signal from)
         public static godot_variant CreateFromSignalTakingOwnershipOfDisposableValue(godot_signal from)
-            => new() { _type = Variant.Type.Signal, _data = { _m_signal = from } };
+            => new() { Type = Variant.Type.Signal, Signal = from };
 
 
         // Explicit name to make it very clear
         // Explicit name to make it very clear
         public static godot_variant CreateFromStringTakingOwnershipOfDisposableValue(godot_string from)
         public static godot_variant CreateFromStringTakingOwnershipOfDisposableValue(godot_string from)
-            => new() { _type = Variant.Type.String, _data = { _m_string = from } };
+            => new() { Type = Variant.Type.String, String = from };
 
 
-        public static unsafe godot_variant CreateFromPackedByteArray(godot_packed_byte_array* from)
+        public static godot_variant CreateFromPackedByteArray(in godot_packed_byte_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_byte_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_byte_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedInt32Array(godot_packed_int32_array* from)
+        public static godot_variant CreateFromPackedInt32Array(in godot_packed_int32_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_int32_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_int32_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedInt64Array(godot_packed_int64_array* from)
+        public static godot_variant CreateFromPackedInt64Array(in godot_packed_int64_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_int64_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_int64_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedFloat32Array(godot_packed_float32_array* from)
+        public static godot_variant CreateFromPackedFloat32Array(in godot_packed_float32_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_float32_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_float32_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedFloat64Array(godot_packed_float64_array* from)
+        public static godot_variant CreateFromPackedFloat64Array(in godot_packed_float64_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_float64_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_float64_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedStringArray(godot_packed_string_array* from)
+        public static godot_variant CreateFromPackedStringArray(in godot_packed_string_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_string_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_string_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedVector2Array(godot_packed_vector2_array* from)
+        public static godot_variant CreateFromPackedVector2Array(in godot_packed_vector2_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_vector2_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_vector2_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedVector3Array(godot_packed_vector3_array* from)
+        public static godot_variant CreateFromPackedVector3Array(in godot_packed_vector3_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_vector3_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_vector3_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromPackedColorArray(godot_packed_color_array* from)
+        public static godot_variant CreateFromPackedColorArray(in godot_packed_color_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_packed_color_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_packed_color_array(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromArray(godot_array* from)
+        public static godot_variant CreateFromArray(godot_array from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_array(&ret, from);
+            NativeFuncs.godotsharp_variant_new_array(out godot_variant ret, from);
             return ret;
             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)
+        public static godot_variant CreateFromDictionary(godot_dictionary from)
         {
         {
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_dictionary(&ret, from);
+            NativeFuncs.godotsharp_variant_new_dictionary(out godot_variant ret, from);
             return ret;
             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)
+        public static godot_variant CreateFromStringName(godot_string_name from)
         {
         {
-            godot_variant ret;
-            godot_string_name src = arg1;
-            NativeFuncs.godotsharp_variant_new_string_name(&ret, &src);
+            NativeFuncs.godotsharp_variant_new_string_name(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromNodePath(ref godot_node_path arg1)
+        public static godot_variant CreateFromNodePath(godot_node_path from)
         {
         {
-            godot_variant ret;
-            godot_node_path src = arg1;
-            NativeFuncs.godotsharp_variant_new_node_path(&ret, &src);
+            NativeFuncs.godotsharp_variant_new_node_path(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
-        public static unsafe godot_variant CreateFromGodotObject(IntPtr from)
+        public static godot_variant CreateFromGodotObject(IntPtr from)
         {
         {
             if (from == IntPtr.Zero)
             if (from == IntPtr.Zero)
                 return new godot_variant();
                 return new godot_variant();
-            godot_variant ret;
-            NativeFuncs.godotsharp_variant_new_object(&ret, from);
+            NativeFuncs.godotsharp_variant_new_object(out godot_variant ret, from);
             return ret;
             return ret;
         }
         }
 
 
         // We avoid the internal call if the stored type is the same we want.
         // 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.ToBool() :
+        public static bool ConvertToBool(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Bool ?
+                p_var.Bool.ToBool() :
                 NativeFuncs.godotsharp_variant_as_bool(p_var).ToBool();
                 NativeFuncs.godotsharp_variant_as_bool(p_var).ToBool();
 
 
-        public static unsafe char ConvertToChar(godot_variant* p_var)
-            => (char)((*p_var)._type == Variant.Type.Int ?
-                (*p_var)._data._int :
+        public static char ConvertToChar(in godot_variant p_var)
+            => (char)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 :
+        public static sbyte ConvertToInt8(in godot_variant p_var)
+            => (sbyte)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 :
+        public static Int16 ConvertToInt16(in godot_variant p_var)
+            => (Int16)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 :
+        public static Int32 ConvertToInt32(in godot_variant p_var)
+            => (Int32)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 Int64 ConvertToInt64(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Int ? p_var.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 :
+        public static byte ConvertToUInt8(in godot_variant p_var)
+            => (byte)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 :
+        public static UInt16 ConvertToUInt16(in godot_variant p_var)
+            => (UInt16)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 :
+        public static UInt32 ConvertToUInt32(in godot_variant p_var)
+            => (UInt32)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 :
+        public static UInt64 ConvertToUInt64(in godot_variant p_var)
+            => (UInt64)(p_var.Type == Variant.Type.Int ?
+                p_var.Int :
                 NativeFuncs.godotsharp_variant_as_int(p_var));
                 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 :
+        public static float ConvertToFloat32(in godot_variant p_var)
+            => (float)(p_var.Type == Variant.Type.Float ?
+                p_var.Float :
                 NativeFuncs.godotsharp_variant_as_float(p_var));
                 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 :
+        public static double ConvertToFloat64(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Float ?
+                p_var.Float :
                 NativeFuncs.godotsharp_variant_as_float(p_var);
                 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 :
+        public static Vector2 ConvertToVector2(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Vector2 ?
+                p_var.Vector2 :
                 NativeFuncs.godotsharp_variant_as_vector2(p_var);
                 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 :
+        public static Vector2i ConvertToVector2i(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Vector2i ?
+                p_var.Vector2i :
                 NativeFuncs.godotsharp_variant_as_vector2i(p_var);
                 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 :
+        public static Rect2 ConvertToRect2(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Rect2 ?
+                p_var.Rect2 :
                 NativeFuncs.godotsharp_variant_as_rect2(p_var);
                 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 :
+        public static Rect2i ConvertToRect2i(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Rect2i ?
+                p_var.Rect2i :
                 NativeFuncs.godotsharp_variant_as_rect2i(p_var);
                 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 :
+        public static unsafe Transform2D ConvertToTransform2D(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Transform2d ?
+                *p_var.Transform2D :
                 NativeFuncs.godotsharp_variant_as_transform2d(p_var);
                 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 :
+        public static Vector3 ConvertToVector3(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Vector3 ?
+                p_var.Vector3 :
                 NativeFuncs.godotsharp_variant_as_vector3(p_var);
                 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 :
+        public static Vector3i ConvertToVector3i(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Vector3i ?
+                p_var.Vector3i :
                 NativeFuncs.godotsharp_variant_as_vector3i(p_var);
                 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 Vector4 ConvertToVector4(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Vector4 ?
+                *p_var.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 Vector4i ConvertToVector4i(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Vector4i ?
+                *p_var.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 :
+        public static unsafe Basis ConvertToBasis(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Basis ?
+                *p_var.Basis :
                 NativeFuncs.godotsharp_variant_as_basis(p_var);
                 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 :
+        public static Quaternion ConvertToQuaternion(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Quaternion ?
+                p_var.Quaternion :
                 NativeFuncs.godotsharp_variant_as_quaternion(p_var);
                 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 :
+        public static unsafe Transform3D ConvertToTransform3D(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Transform3d ?
+                *p_var.Transform3D :
                 NativeFuncs.godotsharp_variant_as_transform3d(p_var);
                 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 Projection ConvertToProjection(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Projection ?
+                *p_var.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 :
+        public static unsafe AABB ConvertToAABB(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Aabb ?
+                *p_var.AABB :
                 NativeFuncs.godotsharp_variant_as_aabb(p_var);
                 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 :
+        public static Color ConvertToColor(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Color ?
+                p_var.Color :
                 NativeFuncs.godotsharp_variant_as_color(p_var);
                 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 :
+        public static Plane ConvertToPlane(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Plane ?
+                p_var.Plane :
                 NativeFuncs.godotsharp_variant_as_plane(p_var);
                 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 IntPtr ConvertToGodotObject(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Object ? p_var.Object : IntPtr.Zero;
 
 
-        public static unsafe RID ConvertToRID(godot_variant* p_var)
-            => (*p_var)._type == Variant.Type.Rid ?
-                (*p_var)._data._m_rid :
+        public static RID ConvertToRID(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Rid ?
+                p_var.RID :
                 NativeFuncs.godotsharp_variant_as_rid(p_var);
                 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) :
+        public static godot_string_name ConvertToStringName(in godot_variant p_var)
+            => p_var.Type == Variant.Type.StringName ?
+                NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName) :
                 NativeFuncs.godotsharp_variant_as_string_name(p_var);
                 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) :
+        public static godot_node_path ConvertToNodePath(in godot_variant p_var)
+            => p_var.Type == Variant.Type.NodePath ?
+                NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath) :
                 NativeFuncs.godotsharp_variant_as_node_path(p_var);
                 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) :
+        public static godot_array ConvertToArray(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Array ?
+                NativeFuncs.godotsharp_array_new_copy(p_var.Array) :
                 NativeFuncs.godotsharp_variant_as_array(p_var);
                 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) :
+        public static godot_dictionary ConvertToDictionary(in godot_variant p_var)
+            => p_var.Type == Variant.Type.Dictionary ?
+                NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary) :
                 NativeFuncs.godotsharp_variant_as_dictionary(p_var);
                 NativeFuncs.godotsharp_variant_as_dictionary(p_var);
     }
     }
 }
 }

+ 38 - 32
modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Runtime.CompilerServices;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 
 
 namespace Godot
 namespace Godot
@@ -42,7 +41,7 @@ namespace Godot
     /// </example>
     /// </example>
     public sealed class NodePath : IDisposable
     public sealed class NodePath : IDisposable
     {
     {
-        public godot_node_path NativeValue;
+        internal godot_node_path.movable NativeValue;
 
 
         ~NodePath()
         ~NodePath()
         {
         {
@@ -61,12 +60,12 @@ namespace Godot
         public void Dispose(bool disposing)
         public void Dispose(bool disposing)
         {
         {
             // Always dispose `NativeValue` even if disposing is true
             // Always dispose `NativeValue` even if disposing is true
-            NativeValue.Dispose();
+            NativeValue.DangerousSelfRef.Dispose();
         }
         }
 
 
         private NodePath(godot_node_path nativeValueToOwn)
         private NodePath(godot_node_path nativeValueToOwn)
         {
         {
-            NativeValue = nativeValueToOwn;
+            NativeValue = (godot_node_path.movable)nativeValueToOwn;
         }
         }
 
 
         // Explicit name to make it very clear
         // Explicit name to make it very clear
@@ -112,7 +111,7 @@ namespace Godot
         public NodePath(string path)
         public NodePath(string path)
         {
         {
             if (!string.IsNullOrEmpty(path))
             if (!string.IsNullOrEmpty(path))
-                NativeValue = NativeFuncs.godotsharp_node_path_new_from_string(path);
+                NativeValue = (godot_node_path.movable)NativeFuncs.godotsharp_node_path_new_from_string(path);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -125,22 +124,21 @@ namespace Godot
         /// Converts this <see cref="NodePath"/> to a string.
         /// Converts this <see cref="NodePath"/> to a string.
         /// </summary>
         /// </summary>
         /// <param name="from">The <see cref="NodePath"/> to convert.</param>
         /// <param name="from">The <see cref="NodePath"/> to convert.</param>
-        public static implicit operator string(NodePath from) => from.ToString();
+        public static implicit operator string(NodePath from) => from?.ToString();
 
 
         /// <summary>
         /// <summary>
         /// Converts this <see cref="NodePath"/> to a string.
         /// Converts this <see cref="NodePath"/> to a string.
         /// </summary>
         /// </summary>
         /// <returns>A string representation of this <see cref="NodePath"/>.</returns>
         /// <returns>A string representation of this <see cref="NodePath"/>.</returns>
-        public override unsafe string ToString()
+        public override string ToString()
         {
         {
             if (IsEmpty)
             if (IsEmpty)
                 return string.Empty;
                 return string.Empty;
 
 
-            godot_string dest;
-            godot_node_path src = NativeValue;
-            NativeFuncs.godotsharp_node_path_as_string(&dest, &src);
+            var src = (godot_node_path)NativeValue;
+            NativeFuncs.godotsharp_node_path_as_string(out godot_string dest, src);
             using (dest)
             using (dest)
-                return Marshaling.mono_string_from_godot(dest);
+                return Marshaling.ConvertStringToManaged(dest);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -161,7 +159,8 @@ namespace Godot
         public NodePath GetAsPropertyPath()
         public NodePath GetAsPropertyPath()
         {
         {
             godot_node_path propertyPath = default;
             godot_node_path propertyPath = default;
-            NativeFuncs.godotsharp_node_path_get_as_property_path(ref NativeValue, ref propertyPath);
+            var self = (godot_node_path)NativeValue;
+            NativeFuncs.godotsharp_node_path_get_as_property_path(self, ref propertyPath);
             return CreateTakingOwnershipOfDisposableValue(propertyPath);
             return CreateTakingOwnershipOfDisposableValue(propertyPath);
         }
         }
 
 
@@ -175,11 +174,12 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <returns>The names concatenated with <c>/</c>.</returns>
         /// <returns>The names concatenated with <c>/</c>.</returns>
-        public unsafe string GetConcatenatedNames()
+        public string GetConcatenatedNames()
         {
         {
-            using godot_string names = default;
-            NativeFuncs.godotsharp_node_path_get_concatenated_names(ref NativeValue, &names);
-            return Marshaling.mono_string_from_godot(names);
+            var self = (godot_node_path)NativeValue;
+            NativeFuncs.godotsharp_node_path_get_concatenated_names(self, out godot_string names);
+            using (names)
+                return Marshaling.ConvertStringToManaged(names);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -193,11 +193,12 @@ namespace Godot
         /// </code>
         /// </code>
         /// </example>
         /// </example>
         /// <returns>The subnames concatenated with <c>:</c>.</returns>
         /// <returns>The subnames concatenated with <c>:</c>.</returns>
-        public unsafe string GetConcatenatedSubNames()
+        public string GetConcatenatedSubNames()
         {
         {
-            using godot_string subNames = default;
-            NativeFuncs.godotsharp_node_path_get_concatenated_subnames(ref NativeValue, &subNames);
-            return Marshaling.mono_string_from_godot(subNames);
+            var self = (godot_node_path)NativeValue;
+            NativeFuncs.godotsharp_node_path_get_concatenated_subnames(self, out godot_string subNames);
+            using (subNames)
+                return Marshaling.ConvertStringToManaged(subNames);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -213,11 +214,12 @@ namespace Godot
         /// </example>
         /// </example>
         /// <param name="idx">The name index.</param>
         /// <param name="idx">The name index.</param>
         /// <returns>The name at the given index <paramref name="idx"/>.</returns>
         /// <returns>The name at the given index <paramref name="idx"/>.</returns>
-        public unsafe string GetName(int idx)
+        public string GetName(int idx)
         {
         {
-            using godot_string name = default;
-            NativeFuncs.godotsharp_node_path_get_name(ref NativeValue, idx, &name);
-            return Marshaling.mono_string_from_godot(name);
+            var self = (godot_node_path)NativeValue;
+            NativeFuncs.godotsharp_node_path_get_name(self, idx, out godot_string name);
+            using (name)
+                return Marshaling.ConvertStringToManaged(name);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -228,7 +230,8 @@ namespace Godot
         /// <returns>The number of node names which make up the path.</returns>
         /// <returns>The number of node names which make up the path.</returns>
         public int GetNameCount()
         public int GetNameCount()
         {
         {
-            return NativeFuncs.godotsharp_node_path_get_name_count(ref NativeValue);
+            var self = (godot_node_path)NativeValue;
+            return NativeFuncs.godotsharp_node_path_get_name_count(self);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -236,11 +239,12 @@ namespace Godot
         /// </summary>
         /// </summary>
         /// <param name="idx">The subname index.</param>
         /// <param name="idx">The subname index.</param>
         /// <returns>The subname at the given index <paramref name="idx"/>.</returns>
         /// <returns>The subname at the given index <paramref name="idx"/>.</returns>
-        public unsafe string GetSubName(int idx)
+        public string GetSubName(int idx)
         {
         {
-            using godot_string subName = default;
-            NativeFuncs.godotsharp_node_path_get_subname(ref NativeValue, idx, &subName);
-            return Marshaling.mono_string_from_godot(subName);
+            var self = (godot_node_path)NativeValue;
+            NativeFuncs.godotsharp_node_path_get_subname(self, idx, out godot_string subName);
+            using (subName)
+                return Marshaling.ConvertStringToManaged(subName);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -251,7 +255,8 @@ namespace Godot
         /// <returns>The number of subnames in the path.</returns>
         /// <returns>The number of subnames in the path.</returns>
         public int GetSubNameCount()
         public int GetSubNameCount()
         {
         {
-            return NativeFuncs.godotsharp_node_path_get_subname_count(ref NativeValue);
+            var self = (godot_node_path)NativeValue;
+            return NativeFuncs.godotsharp_node_path_get_subname_count(self);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -263,13 +268,14 @@ namespace Godot
         /// <returns>If the <see cref="NodePath"/> is an absolute path.</returns>
         /// <returns>If the <see cref="NodePath"/> is an absolute path.</returns>
         public bool IsAbsolute()
         public bool IsAbsolute()
         {
         {
-            return NativeFuncs.godotsharp_node_path_is_absolute(ref NativeValue).ToBool();
+            var self = (godot_node_path)NativeValue;
+            return NativeFuncs.godotsharp_node_path_is_absolute(self).ToBool();
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Returns <see langword="true"/> if the node path is empty.
         /// Returns <see langword="true"/> if the node path is empty.
         /// </summary>
         /// </summary>
         /// <returns>If the <see cref="NodePath"/> is empty.</returns>
         /// <returns>If the <see cref="NodePath"/> is empty.</returns>
-        public bool IsEmpty => godot_node_path.IsEmpty(in NativeValue);
+        public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty;
     }
     }
 }
 }

+ 26 - 27
modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs

@@ -1,7 +1,6 @@
 using System;
 using System;
 using System.Linq;
 using System.Linq;
 using System.Reflection;
 using System.Reflection;
-using System.Runtime.CompilerServices;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 
 
 namespace Godot
 namespace Godot
@@ -47,16 +46,13 @@ namespace Godot
             while (top != null && top != native)
             while (top != null && top != native)
             {
             {
                 foreach (var eventSignal in top.GetEvents(
                 foreach (var eventSignal in top.GetEvents(
-                        BindingFlags.DeclaredOnly | BindingFlags.Instance |
-                        BindingFlags.NonPublic | BindingFlags.Public)
-                    .Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any()))
+                                 BindingFlags.DeclaredOnly | BindingFlags.Instance |
+                                 BindingFlags.NonPublic | BindingFlags.Public)
+                             .Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any()))
                 {
                 {
-                    unsafe
-                    {
-                        using var eventSignalName = new StringName(eventSignal.Name);
-                        godot_string_name eventSignalNameAux = eventSignalName.NativeValue;
-                        NativeFuncs.godotsharp_internal_object_connect_event_signal(NativePtr, &eventSignalNameAux);
-                    }
+                    using var eventSignalName = new StringName(eventSignal.Name);
+                    var eventSignalNameSelf = (godot_string_name)eventSignalName.NativeValue;
+                    NativeFuncs.godotsharp_internal_object_connect_event_signal(NativePtr, eventSignalNameSelf);
                 }
                 }
 
 
                 top = top.BaseType;
                 top = top.BaseType;
@@ -128,11 +124,11 @@ namespace Godot
         /// Converts this <see cref="Object"/> to a string.
         /// Converts this <see cref="Object"/> to a string.
         /// </summary>
         /// </summary>
         /// <returns>A string representation of this object.</returns>
         /// <returns>A string representation of this object.</returns>
-        public override unsafe string ToString()
+        public override string ToString()
         {
         {
-            using godot_string str = default;
-            NativeFuncs.godotsharp_object_to_string(GetPtr(this), &str);
-            return Marshaling.mono_string_from_godot(str);
+            NativeFuncs.godotsharp_object_to_string(GetPtr(this), out godot_string str);
+            using (str)
+                return Marshaling.ConvertStringToManaged(str);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -189,7 +185,7 @@ namespace Godot
             return assemblyName.Name == "GodotSharp" || assemblyName.Name == "GodotSharpEditor";
             return assemblyName.Name == "GodotSharp" || assemblyName.Name == "GodotSharpEditor";
         }
         }
 
 
-        internal unsafe bool InternalGodotScriptCallViaReflection(string method, godot_variant** args, int argCount,
+        internal bool InternalGodotScriptCallViaReflection(string method, NativeVariantPtrArgs args, int argCount,
             out godot_variant ret)
             out godot_variant ret)
         {
         {
             // Performance is not critical here as this will be replaced with source generators.
             // Performance is not critical here as this will be replaced with source generators.
@@ -213,13 +209,13 @@ namespace Godot
 
 
                         for (int i = 0; i < paramCount; i++)
                         for (int i = 0; i < paramCount; i++)
                         {
                         {
-                            invokeParams[i] = Marshaling.variant_to_mono_object_of_type(
+                            invokeParams[i] = Marshaling.ConvertVariantToManagedObjectOfType(
                                 args[i], parameters[i].ParameterType);
                                 args[i], parameters[i].ParameterType);
                         }
                         }
 
 
                         object retObj = methodInfo.Invoke(this, invokeParams);
                         object retObj = methodInfo.Invoke(this, invokeParams);
 
 
-                        ret = Marshaling.mono_object_to_variant(retObj);
+                        ret = Marshaling.ConvertManagedObjectToVariant(retObj);
                         return true;
                         return true;
                     }
                     }
                 }
                 }
@@ -231,7 +227,7 @@ namespace Godot
             return false;
             return false;
         }
         }
 
 
-        internal unsafe bool InternalGodotScriptSetFieldOrPropViaReflection(string name, godot_variant* value)
+        internal bool InternalGodotScriptSetFieldOrPropViaReflection(string name, in godot_variant value)
         {
         {
             // Performance is not critical here as this will be replaced with source generators.
             // Performance is not critical here as this will be replaced with source generators.
             Type top = GetType();
             Type top = GetType();
@@ -245,7 +241,7 @@ namespace Godot
 
 
                 if (fieldInfo != null)
                 if (fieldInfo != null)
                 {
                 {
-                    object valueManaged = Marshaling.variant_to_mono_object_of_type(value, fieldInfo.FieldType);
+                    object valueManaged = Marshaling.ConvertVariantToManagedObjectOfType(value, fieldInfo.FieldType);
                     fieldInfo.SetValue(this, valueManaged);
                     fieldInfo.SetValue(this, valueManaged);
 
 
                     return true;
                     return true;
@@ -257,7 +253,8 @@ namespace Godot
 
 
                 if (propertyInfo != null)
                 if (propertyInfo != null)
                 {
                 {
-                    object valueManaged = Marshaling.variant_to_mono_object_of_type(value, propertyInfo.PropertyType);
+                    object valueManaged =
+                        Marshaling.ConvertVariantToManagedObjectOfType(value, propertyInfo.PropertyType);
                     propertyInfo.SetValue(this, valueManaged);
                     propertyInfo.SetValue(this, valueManaged);
 
 
                     return true;
                     return true;
@@ -284,7 +281,7 @@ namespace Godot
                 if (fieldInfo != null)
                 if (fieldInfo != null)
                 {
                 {
                     object valueManaged = fieldInfo.GetValue(this);
                     object valueManaged = fieldInfo.GetValue(this);
-                    value = Marshaling.mono_object_to_variant(valueManaged);
+                    value = Marshaling.ConvertManagedObjectToVariant(valueManaged);
                     return true;
                     return true;
                 }
                 }
 
 
@@ -295,7 +292,7 @@ namespace Godot
                 if (propertyInfo != null)
                 if (propertyInfo != null)
                 {
                 {
                     object valueManaged = propertyInfo.GetValue(this);
                     object valueManaged = propertyInfo.GetValue(this);
-                    value = Marshaling.mono_object_to_variant(valueManaged);
+                    value = Marshaling.ConvertManagedObjectToVariant(valueManaged);
                     return true;
                     return true;
                 }
                 }
 
 
@@ -306,7 +303,7 @@ namespace Godot
             return false;
             return false;
         }
         }
 
 
-        internal unsafe void InternalRaiseEventSignal(godot_string_name* eventSignalName, godot_variant** args,
+        internal unsafe void InternalRaiseEventSignal(in godot_string_name eventSignalName, NativeVariantPtrArgs args,
             int argc)
             int argc)
         {
         {
             // Performance is not critical here as this will be replaced with source generators.
             // Performance is not critical here as this will be replaced with source generators.
@@ -360,9 +357,9 @@ namespace Godot
 
 
                     var managedArgs = new object[argc];
                     var managedArgs = new object[argc];
 
 
-                    for (uint i = 0; i < argc; i++)
+                    for (int i = 0; i < argc; i++)
                     {
                     {
-                        managedArgs[i] = Marshaling.variant_to_mono_object_of_type(
+                        managedArgs[i] = Marshaling.ConvertVariantToManagedObjectOfType(
                             args[i], parameterInfos[i].ParameterType);
                             args[i], parameterInfos[i].ParameterType);
                     }
                     }
 
 
@@ -379,7 +376,8 @@ namespace Godot
             IntPtr methodBind;
             IntPtr methodBind;
             fixed (char* methodChars = method)
             fixed (char* methodChars = method)
             {
             {
-                methodBind = NativeFuncs.godotsharp_method_bind_get_method(ref type.NativeValue, methodChars);
+                var typeSelf = (godot_string_name)type.NativeValue;
+                methodBind = NativeFuncs.godotsharp_method_bind_get_method(typeSelf, methodChars);
             }
             }
 
 
             if (methodBind == IntPtr.Zero)
             if (methodBind == IntPtr.Zero)
@@ -391,7 +389,8 @@ namespace Godot
         internal static unsafe delegate* unmanaged<IntPtr> ClassDB_get_constructor(StringName type)
         internal static unsafe delegate* unmanaged<IntPtr> ClassDB_get_constructor(StringName type)
         {
         {
             // for some reason the '??' operator doesn't support 'delegate*'
             // for some reason the '??' operator doesn't support 'delegate*'
-            var nativeConstructor = NativeFuncs.godotsharp_get_class_constructor(ref type.NativeValue);
+            var typeSelf = (godot_string_name)type.NativeValue;
+            var nativeConstructor = NativeFuncs.godotsharp_get_class_constructor(typeSelf);
 
 
             if (nativeConstructor == null)
             if (nativeConstructor == null)
                 throw new NativeConstructorNotFoundException(type);
                 throw new NativeConstructorNotFoundException(type);

+ 2 - 2
modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs

@@ -73,7 +73,7 @@ namespace Godot
                     case 3:
                     case 3:
                         return w;
                         return w;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
             set
             set
@@ -93,7 +93,7 @@ namespace Godot
                         w = value;
                         w = value;
                         break;
                         break;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
         }
         }

+ 8 - 6
modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs

@@ -8,19 +8,21 @@ namespace Godot
     {
     {
         private bool _completed;
         private bool _completed;
         private object[] _result;
         private object[] _result;
-        private Action _action;
+        private Action _continuation;
 
 
         public SignalAwaiter(Object source, StringName signal, Object target)
         public SignalAwaiter(Object source, StringName signal, Object target)
         {
         {
-            NativeFuncs.godotsharp_internal_signal_awaiter_connect(Object.GetPtr(source), ref signal.NativeValue,
+            using godot_string_name signalSrc = NativeFuncs.godotsharp_string_name_new_copy(
+                (godot_string_name)(signal?.NativeValue ?? default));
+            NativeFuncs.godotsharp_internal_signal_awaiter_connect(Object.GetPtr(source), in signalSrc,
                 Object.GetPtr(target), GCHandle.ToIntPtr(GCHandle.Alloc(this)));
                 Object.GetPtr(target), GCHandle.ToIntPtr(GCHandle.Alloc(this)));
         }
         }
 
 
         public bool IsCompleted => _completed;
         public bool IsCompleted => _completed;
 
 
-        public void OnCompleted(Action action)
+        public void OnCompleted(Action continuation)
         {
         {
-            this._action = action;
+            _continuation = continuation;
         }
         }
 
 
         public object[] GetResult() => _result;
         public object[] GetResult() => _result;
@@ -48,11 +50,11 @@ namespace Godot
                 object[] signalArgs = new object[argCount];
                 object[] signalArgs = new object[argCount];
 
 
                 for (int i = 0; i < argCount; i++)
                 for (int i = 0; i < argCount; i++)
-                    signalArgs[i] = Marshaling.variant_to_mono_object(args[i]);
+                    signalArgs[i] = Marshaling.ConvertVariantToManagedObject(*args[i]);
 
 
                 awaiter._result = signalArgs;
                 awaiter._result = signalArgs;
 
 
-                awaiter._action?.Invoke();
+                awaiter._continuation?.Invoke();
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {

+ 1 - 1
modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs

@@ -3,7 +3,7 @@ namespace Godot
     /// <summary>
     /// <summary>
     /// Represents a signal defined in an object.
     /// Represents a signal defined in an object.
     /// </summary>
     /// </summary>
-    public struct SignalInfo
+    public readonly struct SignalInfo
     {
     {
         private readonly Object _owner;
         private readonly Object _owner;
         private readonly StringName _signalName;
         private readonly StringName _signalName;

+ 38 - 37
modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs

@@ -1,12 +1,13 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
-using System.Runtime.CompilerServices;
 using System.Security;
 using System.Security;
 using System.Text;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Text.RegularExpressions;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 
 
+#nullable enable
+
 namespace Godot
 namespace Godot
 {
 {
     /// <summary>
     /// <summary>
@@ -1077,12 +1078,12 @@ namespace Godot
         /// <seealso cref="MD5Text(string)"/>
         /// <seealso cref="MD5Text(string)"/>
         /// <param name="instance">The string to hash.</param>
         /// <param name="instance">The string to hash.</param>
         /// <returns>The MD5 hash of the string.</returns>
         /// <returns>The MD5 hash of the string.</returns>
-        public static unsafe byte[] MD5Buffer(this string instance)
+        public static byte[] MD5Buffer(this string instance)
         {
         {
-            using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
-            using godot_packed_byte_array md5Buffer = default;
-            NativeFuncs.godotsharp_string_md5_buffer(&instanceStr, &md5Buffer);
-            return Marshaling.PackedByteArray_to_mono_array(&md5Buffer);
+            using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
+            NativeFuncs.godotsharp_string_md5_buffer(instanceStr, out var md5Buffer);
+            using (md5Buffer)
+                return Marshaling.ConvertNativePackedByteArrayToSystemArray(md5Buffer);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1091,12 +1092,12 @@ namespace Godot
         /// <seealso cref="MD5Buffer(string)"/>
         /// <seealso cref="MD5Buffer(string)"/>
         /// <param name="instance">The string to hash.</param>
         /// <param name="instance">The string to hash.</param>
         /// <returns>The MD5 hash of the string.</returns>
         /// <returns>The MD5 hash of the string.</returns>
-        public static unsafe string MD5Text(this string instance)
+        public static string MD5Text(this string instance)
         {
         {
-            using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
-            using godot_string md5Text = default;
-            NativeFuncs.godotsharp_string_md5_text(&instanceStr, &md5Text);
-            return Marshaling.mono_string_from_godot(md5Text);
+            using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
+            NativeFuncs.godotsharp_string_md5_text(instanceStr, out var md5Text);
+            using (md5Text)
+                return Marshaling.ConvertStringToManaged(md5Text);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1251,11 +1252,11 @@ namespace Godot
         /// <param name="what">The substring to search in the string.</param>
         /// <param name="what">The substring to search in the string.</param>
         /// <param name="from">The position at which to start searching.</param>
         /// <param name="from">The position at which to start searching.</param>
         /// <returns>The position at which the substring was found, or -1 if not found.</returns>
         /// <returns>The position at which the substring was found, or -1 if not found.</returns>
-        public static unsafe int RFind(this string instance, string what, int from = -1)
+        public static int RFind(this string instance, string what, int from = -1)
         {
         {
-            using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
-            using godot_string whatStr = Marshaling.mono_string_to_godot(instance);
-            return NativeFuncs.godotsharp_string_rfind(&instanceStr, &whatStr, from);
+            using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
+            using godot_string whatStr = Marshaling.ConvertStringToNative(instance);
+            return NativeFuncs.godotsharp_string_rfind(instanceStr, whatStr, from);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1267,11 +1268,11 @@ namespace Godot
         /// <param name="what">The substring to search in the string.</param>
         /// <param name="what">The substring to search in the string.</param>
         /// <param name="from">The position at which to start searching.</param>
         /// <param name="from">The position at which to start searching.</param>
         /// <returns>The position at which the substring was found, or -1 if not found.</returns>
         /// <returns>The position at which the substring was found, or -1 if not found.</returns>
-        public static unsafe int RFindN(this string instance, string what, int from = -1)
+        public static int RFindN(this string instance, string what, int from = -1)
         {
         {
-            using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
-            using godot_string whatStr = Marshaling.mono_string_to_godot(instance);
-            return NativeFuncs.godotsharp_string_rfindn(&instanceStr, &whatStr, from);
+            using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
+            using godot_string whatStr = Marshaling.ConvertStringToNative(instance);
+            return NativeFuncs.godotsharp_string_rfindn(instanceStr, whatStr, from);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1326,12 +1327,12 @@ namespace Godot
         /// <seealso cref="SHA256Text(string)"/>
         /// <seealso cref="SHA256Text(string)"/>
         /// <param name="instance">The string to hash.</param>
         /// <param name="instance">The string to hash.</param>
         /// <returns>The SHA-256 hash of the string.</returns>
         /// <returns>The SHA-256 hash of the string.</returns>
-        public static unsafe byte[] SHA256Buffer(this string instance)
+        public static byte[] SHA256Buffer(this string instance)
         {
         {
-            using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
-            using godot_packed_byte_array sha256Buffer = default;
-            NativeFuncs.godotsharp_string_sha256_buffer(&instanceStr, &sha256Buffer);
-            return Marshaling.PackedByteArray_to_mono_array(&sha256Buffer);
+            using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
+            NativeFuncs.godotsharp_string_sha256_buffer(instanceStr, out var sha256Buffer);
+            using (sha256Buffer)
+                return Marshaling.ConvertNativePackedByteArrayToSystemArray(sha256Buffer);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1340,12 +1341,12 @@ namespace Godot
         /// <seealso cref="SHA256Buffer(string)"/>
         /// <seealso cref="SHA256Buffer(string)"/>
         /// <param name="instance">The string to hash.</param>
         /// <param name="instance">The string to hash.</param>
         /// <returns>The SHA-256 hash of the string.</returns>
         /// <returns>The SHA-256 hash of the string.</returns>
-        public static unsafe string SHA256Text(this string instance)
+        public static string SHA256Text(this string instance)
         {
         {
-            using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
-            using godot_string sha256Text = default;
-            NativeFuncs.godotsharp_string_sha256_text(&instanceStr, &sha256Text);
-            return Marshaling.mono_string_from_godot(sha256Text);
+            using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
+            NativeFuncs.godotsharp_string_sha256_text(instanceStr, out var sha256Text);
+            using (sha256Text)
+                return Marshaling.ConvertStringToManaged(sha256Text);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1396,12 +1397,12 @@ namespace Godot
         /// <summary>
         /// <summary>
         /// Returns a simplified canonical path.
         /// Returns a simplified canonical path.
         /// </summary>
         /// </summary>
-        public static unsafe string SimplifyPath(this string instance)
+        public static string SimplifyPath(this string instance)
         {
         {
-            using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
-            using godot_string simplifiedPath = default;
-            NativeFuncs.godotsharp_string_simplify_path(&instanceStr, &simplifiedPath);
-            return Marshaling.mono_string_from_godot(simplifiedPath);
+            using godot_string instanceStr = Marshaling.ConvertStringToNative(instance);
+            NativeFuncs.godotsharp_string_simplify_path(instanceStr, out godot_string simplifiedPath);
+            using (simplifiedPath)
+                return Marshaling.ConvertStringToManaged(simplifiedPath);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1602,7 +1603,7 @@ namespace Godot
         /// <seealso cref="XMLUnescape(string)"/>
         /// <seealso cref="XMLUnescape(string)"/>
         /// <param name="instance">The string to escape.</param>
         /// <param name="instance">The string to escape.</param>
         /// <returns>The escaped string.</returns>
         /// <returns>The escaped string.</returns>
-        public static string XMLEscape(this string instance)
+        public static string? XMLEscape(this string instance)
         {
         {
             return SecurityElement.Escape(instance);
             return SecurityElement.Escape(instance);
         }
         }
@@ -1614,9 +1615,9 @@ namespace Godot
         /// <seealso cref="XMLEscape(string)"/>
         /// <seealso cref="XMLEscape(string)"/>
         /// <param name="instance">The string to unescape.</param>
         /// <param name="instance">The string to unescape.</param>
         /// <returns>The unescaped string.</returns>
         /// <returns>The unescaped string.</returns>
-        public static string XMLUnescape(this string instance)
+        public static string? XMLUnescape(this string instance)
         {
         {
-            return SecurityElement.FromString(instance).Text;
+            return SecurityElement.FromString(instance)?.Text;
         }
         }
     }
     }
 }
 }

+ 10 - 12
modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Runtime.CompilerServices;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 
 
 namespace Godot
 namespace Godot
@@ -13,7 +12,7 @@ namespace Godot
     /// </summary>
     /// </summary>
     public sealed class StringName : IDisposable
     public sealed class StringName : IDisposable
     {
     {
-        public godot_string_name NativeValue;
+        internal godot_string_name.movable NativeValue;
 
 
         ~StringName()
         ~StringName()
         {
         {
@@ -32,12 +31,12 @@ namespace Godot
         public void Dispose(bool disposing)
         public void Dispose(bool disposing)
         {
         {
             // Always dispose `NativeValue` even if disposing is true
             // Always dispose `NativeValue` even if disposing is true
-            NativeValue.Dispose();
+            NativeValue.DangerousSelfRef.Dispose();
         }
         }
 
 
         private StringName(godot_string_name nativeValueToOwn)
         private StringName(godot_string_name nativeValueToOwn)
         {
         {
-            NativeValue = nativeValueToOwn;
+            NativeValue = (godot_string_name.movable)nativeValueToOwn;
         }
         }
 
 
         // Explicit name to make it very clear
         // Explicit name to make it very clear
@@ -58,7 +57,7 @@ namespace Godot
         public StringName(string name)
         public StringName(string name)
         {
         {
             if (!string.IsNullOrEmpty(name))
             if (!string.IsNullOrEmpty(name))
-                NativeValue = NativeFuncs.godotsharp_string_name_new_from_string(name);
+                NativeValue = (godot_string_name.movable)NativeFuncs.godotsharp_string_name_new_from_string(name);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -71,28 +70,27 @@ namespace Godot
         /// Converts a <see cref="StringName"/> to a string.
         /// Converts a <see cref="StringName"/> to a string.
         /// </summary>
         /// </summary>
         /// <param name="from">The <see cref="StringName"/> to convert.</param>
         /// <param name="from">The <see cref="StringName"/> to convert.</param>
-        public static implicit operator string(StringName from) => from.ToString();
+        public static implicit operator string(StringName from) => from?.ToString();
 
 
         /// <summary>
         /// <summary>
         /// Converts this <see cref="StringName"/> to a string.
         /// Converts this <see cref="StringName"/> to a string.
         /// </summary>
         /// </summary>
         /// <returns>A string representation of this <see cref="StringName"/>.</returns>
         /// <returns>A string representation of this <see cref="StringName"/>.</returns>
-        public override unsafe string ToString()
+        public override string ToString()
         {
         {
             if (IsEmpty)
             if (IsEmpty)
                 return string.Empty;
                 return string.Empty;
 
 
-            godot_string dest;
-            godot_string_name src = NativeValue;
-            NativeFuncs.godotsharp_string_name_as_string(&dest, &src);
+            var src = (godot_string_name)NativeValue;
+            NativeFuncs.godotsharp_string_name_as_string(out godot_string dest, src);
             using (dest)
             using (dest)
-                return Marshaling.mono_string_from_godot(dest);
+                return Marshaling.ConvertStringToManaged(dest);
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Check whether this <see cref="StringName"/> is empty.
         /// Check whether this <see cref="StringName"/> is empty.
         /// </summary>
         /// </summary>
         /// <returns>If the <see cref="StringName"/> is empty.</returns>
         /// <returns>If the <see cref="StringName"/> is empty.</returns>
-        public bool IsEmpty => godot_string_name.IsEmpty(in NativeValue);
+        public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty;
     }
     }
 }
 }

+ 2 - 2
modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs

@@ -93,7 +93,7 @@ namespace Godot
                     case 2:
                     case 2:
                         return origin;
                         return origin;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(column));
                 }
                 }
             }
             }
             set
             set
@@ -110,7 +110,7 @@ namespace Godot
                         origin = value;
                         origin = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(column));
                 }
                 }
             }
             }
         }
         }

+ 6 - 6
modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs

@@ -52,7 +52,7 @@ namespace Godot
                     case 3:
                     case 3:
                         return origin;
                         return origin;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(column));
                 }
                 }
             }
             }
             set
             set
@@ -72,7 +72,7 @@ namespace Godot
                         origin = value;
                         origin = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(column));
                 }
                 }
             }
             }
         }
         }
@@ -168,7 +168,7 @@ namespace Godot
         /// <param name="target">The object to look at.</param>
         /// <param name="target">The object to look at.</param>
         /// <param name="up">The relative up direction.</param>
         /// <param name="up">The relative up direction.</param>
         /// <returns>The resulting transform.</returns>
         /// <returns>The resulting transform.</returns>
-        public Transform3D LookingAt(Vector3 target, Vector3 up)
+        public readonly Transform3D LookingAt(Vector3 target, Vector3 up)
         {
         {
             Transform3D t = this;
             Transform3D t = this;
             t.SetLookAt(origin, target, up);
             t.SetLookAt(origin, target, up);
@@ -194,7 +194,7 @@ namespace Godot
         /// <param name="axis">The axis to rotate around. Must be normalized.</param>
         /// <param name="axis">The axis to rotate around. Must be normalized.</param>
         /// <param name="angle">The angle to rotate, in radians.</param>
         /// <param name="angle">The angle to rotate, in radians.</param>
         /// <returns>The rotated transformation matrix.</returns>
         /// <returns>The rotated transformation matrix.</returns>
-        public Transform3D Rotated(Vector3 axis, real_t angle)
+        public readonly Transform3D Rotated(Vector3 axis, real_t angle)
         {
         {
             return new Transform3D(new Basis(axis, angle), new Vector3()) * this;
             return new Transform3D(new Basis(axis, angle), new Vector3()) * this;
         }
         }
@@ -443,7 +443,7 @@ namespace Godot
         /// </summary>
         /// </summary>
         /// <param name="obj">The object to compare with.</param>
         /// <param name="obj">The object to compare with.</param>
         /// <returns>Whether or not the transform and the object are exactly equal.</returns>
         /// <returns>Whether or not the transform and the object are exactly equal.</returns>
-        public override bool Equals(object obj)
+        public override readonly bool Equals(object obj)
         {
         {
             if (obj is Transform3D)
             if (obj is Transform3D)
             {
             {
@@ -460,7 +460,7 @@ namespace Godot
         /// </summary>
         /// </summary>
         /// <param name="other">The other transform to compare.</param>
         /// <param name="other">The other transform to compare.</param>
         /// <returns>Whether or not the matrices are exactly equal.</returns>
         /// <returns>Whether or not the matrices are exactly equal.</returns>
-        public bool Equals(Transform3D other)
+        public readonly bool Equals(Transform3D other)
         {
         {
             return basis.Equals(other.basis) && origin.Equals(other.origin);
             return basis.Equals(other.basis) && origin.Equals(other.origin);
         }
         }

+ 2 - 2
modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs

@@ -62,7 +62,7 @@ namespace Godot
                     case 1:
                     case 1:
                         return y;
                         return y;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
             set
             set
@@ -76,7 +76,7 @@ namespace Godot
                         y = value;
                         y = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
         }
         }

+ 2 - 2
modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs

@@ -62,7 +62,7 @@ namespace Godot
                     case 1:
                     case 1:
                         return y;
                         return y;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
             set
             set
@@ -76,7 +76,7 @@ namespace Godot
                         y = value;
                         y = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
         }
         }

+ 2 - 2
modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs

@@ -74,7 +74,7 @@ namespace Godot
                     case 2:
                     case 2:
                         return z;
                         return z;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
             set
             set
@@ -91,7 +91,7 @@ namespace Godot
                         z = value;
                         z = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
         }
         }

+ 2 - 2
modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs

@@ -74,7 +74,7 @@ namespace Godot
                     case 2:
                     case 2:
                         return z;
                         return z;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
             set
             set
@@ -91,7 +91,7 @@ namespace Godot
                         z = value;
                         z = value;
                         return;
                         return;
                     default:
                     default:
-                        throw new IndexOutOfRangeException();
+                        throw new ArgumentOutOfRangeException(nameof(index));
                 }
                 }
             }
             }
         }
         }

+ 3 - 0
modules/mono/glue/GodotSharp/GodotSharp/FodyWeavers.xml

@@ -0,0 +1,3 @@
+<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
+  <InlineIL />
+</Weavers>

+ 93 - 0
modules/mono/glue/GodotSharp/GodotSharp/GenerateGodotCustomUnsafe.targets

@@ -0,0 +1,93 @@
+<Project>
+  <!-- Generate Godot.NativeInterop.CustomUnsafe C# class-->
+
+  <!--
+  Ref structs are not allowed as generic type parameters, so we can't use Unsafe.AsPointer<T>/AsRef<T>.
+  As a workaround we generate overloads of those methods for our structs using Fody with inline IL.
+  -->
+
+  <ItemGroup>
+    <PackageReference Include="Fody" Version="6.6.0" PrivateAssets="all" />
+    <PackageReference Include="InlineIL.Fody" Version="1.7.1" PrivateAssets="all" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <GodotInteropStructs Include="godot_ref" />
+    <GodotInteropStructs Include="godot_variant_call_error" />
+    <GodotInteropStructs Include="godot_variant" />
+    <GodotInteropStructs Include="godot_string" />
+    <GodotInteropStructs Include="godot_string_name" />
+    <GodotInteropStructs Include="godot_node_path" />
+    <GodotInteropStructs Include="godot_signal" />
+    <GodotInteropStructs Include="godot_callable" />
+    <GodotInteropStructs Include="godot_array" />
+    <GodotInteropStructs Include="godot_dictionary" />
+    <GodotInteropStructs Include="godot_packed_byte_array" />
+    <GodotInteropStructs Include="godot_packed_int32_array" />
+    <GodotInteropStructs Include="godot_packed_int64_array" />
+    <GodotInteropStructs Include="godot_packed_float32_array" />
+    <GodotInteropStructs Include="godot_packed_float64_array" />
+    <GodotInteropStructs Include="godot_packed_string_array" />
+    <GodotInteropStructs Include="godot_packed_vector2_array" />
+    <GodotInteropStructs Include="godot_packed_vector3_array" />
+    <GodotInteropStructs Include="godot_packed_color_array" />
+  </ItemGroup>
+
+  <Target Name="GenerateGodotCustomUnsafe"
+          DependsOnTargets="_GenerateGodotCustomUnsafe"
+          BeforeTargets="PrepareForBuild;CompileDesignTime;BeforeCompile;CoreCompile">
+    <ItemGroup>
+      <Compile Include="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs" />
+      <FileWrites Include="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs" />
+    </ItemGroup>
+  </Target>
+  <Target Name="_GenerateGodotCustomUnsafe"
+          Inputs="$(MSBuildProjectFile);$(MSBuildThisFileDirectory);@(GodotInteropStructs)"
+          Outputs="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs">
+    <PropertyGroup>
+      <GodotInteropStruct>%(GodotInteropStructs.Identity)</GodotInteropStruct>
+      <GenerateGodotCustomUnsafeCode><![CDATA[
+using System.Runtime.CompilerServices%3b
+using InlineIL%3b
+using static InlineIL.IL.Emit%3b
+
+namespace Godot.NativeInterop
+{
+    public static partial class CustomUnsafe
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static unsafe $(GodotInteropStruct)* AsPointer(ref $(GodotInteropStruct) value)
+        {
+            Ldarg(nameof(value))%3b
+            Conv_U()%3b
+            return ($(GodotInteropStruct)*)IL.ReturnPointer()%3b
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static unsafe $(GodotInteropStruct)* ReadOnlyRefAsPointer(in $(GodotInteropStruct) value)
+        {
+            Ldarg(nameof(value))%3b
+            Conv_U()%3b
+            return ($(GodotInteropStruct)*)IL.ReturnPointer()%3b
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static unsafe ref $(GodotInteropStruct) AsRef($(GodotInteropStruct)* source)
+        {
+            return ref *source%3b
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static unsafe ref $(GodotInteropStruct) AsRef(in $(GodotInteropStruct) source)
+        {
+            return ref *ReadOnlyRefAsPointer(in source)%3b
+        }
+    }
+}
+]]></GenerateGodotCustomUnsafeCode>
+    </PropertyGroup>
+    <WriteLinesToFile Lines="$(GenerateGodotCustomUnsafeCode)"
+                      File="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs"
+                      Overwrite="True" WriteOnlyWhenDifferent="True" />
+  </Target>
+</Project>

+ 9 - 0
modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj

@@ -10,6 +10,8 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <LangVersion>9</LangVersion>
     <LangVersion>9</LangVersion>
 
 
+    <AnalysisMode>Recommended</AnalysisMode>
+
     <!-- Disabled temporarily as it pollutes the warnings, but we need to document public APIs. -->
     <!-- Disabled temporarily as it pollutes the warnings, but we need to document public APIs. -->
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
@@ -20,6 +22,12 @@
     <PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
     <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" /-->
     <!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
   </ItemGroup>
   </ItemGroup>
+  <!-- Targets for generating Godot.NativeInterop.CustomUnsafe -->
+  <Import Project="GenerateGodotCustomUnsafe.targets" />
+  <ItemGroup>
+    <None Include="GenerateGodotCustomUnsafe.targets" />
+  </ItemGroup>
+  <!-- Sources -->
   <ItemGroup>
   <ItemGroup>
     <Compile Include="Core\AABB.cs" />
     <Compile Include="Core\AABB.cs" />
     <Compile Include="Core\Array.cs" />
     <Compile Include="Core\Array.cs" />
@@ -62,6 +70,7 @@
     <Compile Include="Core\NativeInterop\ExceptionUtils.cs" />
     <Compile Include="Core\NativeInterop\ExceptionUtils.cs" />
     <Compile Include="Core\NativeInterop\InteropUtils.cs" />
     <Compile Include="Core\NativeInterop\InteropUtils.cs" />
     <Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
     <Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
+    <Compile Include="Core\NativeInterop\NativeVariantPtrArgs.cs" />
     <Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
     <Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
     <Compile Include="Core\NativeInterop\VariantUtils.cs" />
     <Compile Include="Core\NativeInterop\VariantUtils.cs" />
     <Compile Include="Core\NodePath.cs" />
     <Compile Include="Core\NodePath.cs" />

+ 18 - 1
modules/mono/glue/runtime_interop.cpp

@@ -445,6 +445,21 @@ GD_PINVOKE_EXPORT bool godotsharp_callable_get_data_for_marshalling(const Callab
 	}
 	}
 }
 }
 
 
+GD_PINVOKE_EXPORT godot_variant godotsharp_callable_call(Callable *p_callable, const Variant **p_args, const int32_t p_arg_count, Callable::CallError *p_call_error) {
+	godot_variant ret;
+	memnew_placement(&ret, Variant);
+
+	Variant *ret_val = (Variant *)&ret;
+
+	p_callable->callp(p_args, p_arg_count, *ret_val, *p_call_error);
+
+	return ret;
+}
+
+GD_PINVOKE_EXPORT void godotsharp_callable_call_deferred(Callable *p_callable, const Variant **p_args, const int32_t p_arg_count) {
+	p_callable->call_deferredp(p_args, p_arg_count);
+}
+
 // GDNative functions
 // GDNative functions
 
 
 // gdnative.h
 // gdnative.h
@@ -1241,7 +1256,7 @@ GD_PINVOKE_EXPORT void godotsharp_object_to_string(Object *p_ptr, godot_string *
 #endif
 #endif
 
 
 // We need this to prevent the functions from being stripped.
 // We need this to prevent the functions from being stripped.
-void *godotsharp_pinvoke_funcs[176] = {
+void *godotsharp_pinvoke_funcs[178] = {
 	(void *)godotsharp_method_bind_get_method,
 	(void *)godotsharp_method_bind_get_method,
 	(void *)godotsharp_get_class_constructor,
 	(void *)godotsharp_get_class_constructor,
 	(void *)godotsharp_engine_get_singleton,
 	(void *)godotsharp_engine_get_singleton,
@@ -1274,6 +1289,8 @@ void *godotsharp_pinvoke_funcs[176] = {
 	(void *)godotsharp_packed_string_array_add,
 	(void *)godotsharp_packed_string_array_add,
 	(void *)godotsharp_callable_new_with_delegate,
 	(void *)godotsharp_callable_new_with_delegate,
 	(void *)godotsharp_callable_get_data_for_marshalling,
 	(void *)godotsharp_callable_get_data_for_marshalling,
+	(void *)godotsharp_callable_call,
+	(void *)godotsharp_callable_call_deferred,
 	(void *)godotsharp_method_bind_ptrcall,
 	(void *)godotsharp_method_bind_ptrcall,
 	(void *)godotsharp_method_bind_call,
 	(void *)godotsharp_method_bind_call,
 	(void *)godotsharp_variant_new_string_name,
 	(void *)godotsharp_variant_new_string_name,

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików