Explorar o código

C#: Add DynamicGodotObject class

Expands to Object.call, Object.set and Object.get for accessing members. This means it can also access members from scripts written in other languages, like GDScript.
Ignacio Etcheverry %!s(int64=6) %!d(string=hai) anos
pai
achega
bb6814aef0

+ 7 - 14
modules/mono/editor/bindings_generator.cpp

@@ -98,7 +98,7 @@
 #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 BINDINGS_GENERATOR_VERSION UINT32_C(7)
+#define BINDINGS_GENERATOR_VERSION UINT32_C(8)
 
 const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
 
@@ -1912,20 +1912,13 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
 				String vararg_arg = "arg" + argc_str;
 				String real_argc_str = itos(p_imethod.arguments.size() - 1); // Arguments count without vararg
 
-				p_output.push_back("\tVector<Variant> varargs;\n"
-								   "\tint vararg_length = mono_array_length(");
+				p_output.push_back("\tint vararg_length = mono_array_length(");
 				p_output.push_back(vararg_arg);
 				p_output.push_back(");\n\tint total_length = ");
 				p_output.push_back(real_argc_str);
-				p_output.push_back(" + vararg_length;\n\t");
-				p_output.push_back(err_fail_macro);
-				p_output.push_back("(varargs.resize(vararg_length) != OK");
-				p_output.push_back(fail_ret);
-				p_output.push_back(");\n\tVector<Variant*> " C_LOCAL_PTRCALL_ARGS ";\n\t");
-				p_output.push_back(err_fail_macro);
-				p_output.push_back("(call_args.resize(total_length) != OK");
-				p_output.push_back(fail_ret);
-				p_output.push_back(");\n");
+				p_output.push_back(" + vararg_length;\n"
+								   "\tArgumentsVector<Variant> varargs(vararg_length);\n"
+								   "\tArgumentsVector<const Variant *> " C_LOCAL_PTRCALL_ARGS "(total_length);\n");
 				p_output.push_back(c_in_statements);
 				p_output.push_back("\tfor (int i = 0; i < vararg_length; i++) " OPEN_BLOCK
 								   "\t\tMonoObject* elem = mono_array_get(");
@@ -1934,7 +1927,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
 								   "\t\tvarargs.set(i, GDMonoMarshal::mono_object_to_variant(elem));\n"
 								   "\t\t" C_LOCAL_PTRCALL_ARGS ".set(");
 				p_output.push_back(real_argc_str);
-				p_output.push_back(" + i, &varargs.write[i]);\n\t" CLOSE_BLOCK);
+				p_output.push_back(" + i, &varargs.get(i));\n\t" CLOSE_BLOCK);
 			} else {
 				p_output.push_back(c_in_statements);
 				p_output.push_back("\tconst void* " C_LOCAL_PTRCALL_ARGS "[");
@@ -1956,7 +1949,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
 			}
 
 			p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
-			p_output.push_back(p_imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
+			p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
 			p_output.push_back(", total_length, vcall_error);\n");
 
 			// See the comment on the C_LOCAL_VARARG_RET declaration

+ 213 - 0
modules/mono/glue/Managed/Files/DynamicObject.cs

@@ -0,0 +1,213 @@
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+
+namespace Godot
+{
+    /// <summary>
+    /// Represents an <see cref="Godot.Object"/> whose members can be dynamically accessed at runtime through the Variant API.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// The <see cref="Godot.DynamicGodotObject"/> class enables access to the Variant
+    /// members of a <see cref="Godot.Object"/> instance at runtime.
+    /// </para>
+    /// <para>
+    /// This allows accessing the class members using their original names in the engine as well as the members from the
+    /// script attached to the <see cref="Godot.Object"/>, regardless of the scripting language it was written in.
+    /// </para>
+    /// </remarks>
+    /// <example>
+    /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Godot.Object"/>.
+    /// <code>
+    /// dynamic sprite = GetNode("Sprite").DynamicGodotObject;
+    /// sprite.add_child(this);
+    ///
+    /// if ((sprite.hframes * sprite.vframes) > 0)
+    ///     sprite.frame = 0;
+    /// </code>
+    /// </example>
+    /// <example>
+    /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the members of the script attached to a <see cref="Godot.Object"/>.
+    /// <code>
+    /// dynamic childNode = GetNode("ChildNode").DynamicGodotObject;
+    ///
+    /// if (childNode.print_allowed)
+    /// {
+    ///     childNode.message = "Hello from C#";
+    ///     childNode.print_message(3);
+    /// }
+    /// </code>
+    /// The <c>ChildNode</c> node has the following GDScript script attached:
+    /// <code>
+    /// // # ChildNode.gd
+    /// // var print_allowed = true
+    /// // var message = ""
+    /// //
+    /// // func print_message(times):
+    /// //     for i in times:
+    /// //         print(message)
+    /// </code>
+    /// </example>
+    public class DynamicGodotObject : DynamicObject
+    {
+        /// <summary>
+        /// Gets the <see cref="Godot.Object"/> associated with this <see cref="Godot.DynamicGodotObject"/>.
+        /// </summary>
+        public Object Value { get; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Godot.DynamicGodotObject"/> class.
+        /// </summary>
+        /// <param name="godotObject">
+        /// The <see cref="Godot.Object"/> that will be associated with this <see cref="Godot.DynamicGodotObject"/>.
+        /// </param>
+        /// <exception cref="System.ArgumentNullException">
+        /// Thrown when the <paramref name="godotObject"/> parameter is null.
+        /// </exception>
+        public DynamicGodotObject(Object godotObject)
+        {
+            if (godotObject == null)
+                throw new ArgumentNullException(nameof(godotObject));
+
+            this.Value = godotObject;
+        }
+
+        public override IEnumerable<string> GetDynamicMemberNames()
+        {
+            return godot_icall_DynamicGodotObject_SetMemberList(Object.GetPtr(Value));
+        }
+
+        public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
+        {
+            switch (binder.Operation)
+            {
+                case ExpressionType.Equal:
+                case ExpressionType.NotEqual:
+                    if (binder.ReturnType == typeof(bool) || binder.ReturnType.IsAssignableFrom(typeof(bool)))
+                    {
+                        if (arg == null)
+                        {
+                            bool boolResult = Object.IsInstanceValid(Value);
+
+                            if (binder.Operation == ExpressionType.Equal)
+                                boolResult = !boolResult;
+
+                            result = boolResult;
+                            return true;
+                        }
+
+                        if (arg is Object other)
+                        {
+                            bool boolResult = (Value == other);
+
+                            if (binder.Operation == ExpressionType.NotEqual)
+                                boolResult = !boolResult;
+
+                            result = boolResult;
+                            return true;
+                        }
+                    }
+
+                    break;
+                default:
+                    // We're not implementing operators <, <=, >, and >= (LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual).
+                    // These are used on the actual pointers in variant_op.cpp. It's better to let the user do that explicitly.
+                    break;
+            }
+
+            return base.TryBinaryOperation(binder, arg, out result);
+        }
+
+        public override bool TryConvert(ConvertBinder binder, out object result)
+        {
+            if (binder.Type == typeof(Object))
+            {
+                result = Value;
+                return true;
+            }
+
+            if (typeof(Object).IsAssignableFrom(binder.Type))
+            {
+                // Throws InvalidCastException when the cast fails
+                result = Convert.ChangeType(Value, binder.Type);
+                return true;
+            }
+
+            return base.TryConvert(binder, out result);
+        }
+
+        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
+        {
+            if (indexes.Length == 1)
+            {
+                if (indexes[0] is string name)
+                {
+                    return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), name, out result);
+                }
+            }
+
+            return base.TryGetIndex(binder, indexes, out result);
+        }
+
+        public override bool TryGetMember(GetMemberBinder binder, out object result)
+        {
+            return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), binder.Name, out result);
+        }
+
+        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
+        {
+            return godot_icall_DynamicGodotObject_InvokeMember(Object.GetPtr(Value), binder.Name, args, out result);
+        }
+
+        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
+        {
+            if (indexes.Length == 1)
+            {
+                if (indexes[0] is string name)
+                {
+                    return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), name, value);
+                }
+            }
+
+            return base.TrySetIndex(binder, indexes, value);
+        }
+
+        public override bool TrySetMember(SetMemberBinder binder, object value)
+        {
+            return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), binder.Name, value);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static string[] godot_icall_DynamicGodotObject_SetMemberList(IntPtr godotObject);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static bool godot_icall_DynamicGodotObject_InvokeMember(IntPtr godotObject, string name, object[] args, out object result);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static bool godot_icall_DynamicGodotObject_GetMember(IntPtr godotObject, string name, out object result);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static bool godot_icall_DynamicGodotObject_SetMember(IntPtr godotObject, string name, object value);
+
+        #region We don't override these methods
+
+        // Looks like this is not usable from C#
+        //public override bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result);
+
+        // Object members cannot be deleted
+        //public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
+        //public override bool TryDeleteMember(DeleteMemberBinder binder);
+
+        // Invokation on the object itself, e.g.: obj(param)
+        //public override bool TryInvoke(InvokeBinder binder, object[] args, out object result);
+
+        // No unnary operations to handle
+        //public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result);
+
+        #endregion
+    }
+}

+ 28 - 0
modules/mono/glue/Managed/Files/Object.base.cs

@@ -73,11 +73,39 @@ namespace Godot
             disposed = true;
         }
 
+        /// <summary>
+        /// Returns a new <see cref="Godot.SignalAwaiter"/> awaiter configured to complete when the instance
+        /// <paramref name="source"/> emits the signal specified by the <paramref name="signal"/> parameter.
+        /// </summary>
+        /// <param name="source">
+        /// The instance the awaiter will be listening to.
+        /// </param>
+        /// <param name="signal">
+        /// The signal the awaiter will be waiting for.
+        /// </param>
+        /// <example>
+        /// This sample prints a message once every frame up to 100 times.
+        /// <code>
+        /// public override void _Ready()
+        /// {
+        ///     for (int i = 0; i < 100; i++)
+        ///     {
+        ///         await ToSignal(GetTree(), "idle_frame");
+        ///         GD.Print($"Frame {i}");
+        ///     }
+        /// }
+        /// </code>
+        /// </example>
         public SignalAwaiter ToSignal(Object source, string signal)
         {
             return new SignalAwaiter(source, signal, this);
         }
 
+        /// <summary>
+        /// Gets a new <see cref="Godot.DynamicGodotObject"/> associated with this instance.
+        /// </summary>
+        public dynamic DynamicObject => new DynamicGodotObject(this);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal extern static IntPtr godot_icall_Object_Ctor(Object obj);
 

+ 60 - 0
modules/mono/glue/arguments_vector.h

@@ -0,0 +1,60 @@
+/*************************************************************************/
+/*  arguments_vector.h                                                   */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef ARGUMENTS_VECTOR_H
+#define ARGUMENTS_VECTOR_H
+
+#include "core/os/memory.h"
+
+template <typename T, int POOL_SIZE = 5>
+struct ArgumentsVector {
+
+private:
+	T pool[POOL_SIZE];
+	T *_ptr;
+
+	ArgumentsVector();
+	ArgumentsVector(const ArgumentsVector &);
+
+public:
+	T *ptr() { return _ptr; }
+	T &get(int p_idx) { return _ptr[p_idx]; }
+	void set(int p_idx, const T &p_value) { _ptr[p_idx] = p_value; }
+
+	explicit ArgumentsVector(int size) {
+		if (size <= POOL_SIZE) {
+			_ptr = pool;
+		} else {
+			_ptr = memnew_arr(T, size);
+		}
+	}
+};
+
+#endif // ARGUMENTS_VECTOR_H

+ 68 - 1
modules/mono/glue/base_object_glue.cpp

@@ -36,9 +36,11 @@
 #include "core/string_name.h"
 
 #include "../csharp_script.h"
+#include "../mono_gd/gd_mono_class.h"
 #include "../mono_gd/gd_mono_internals.h"
 #include "../mono_gd/gd_mono_utils.h"
 #include "../signal_awaiter_utils.h"
+#include "arguments_vector.h"
 
 Object *godot_icall_Object_Ctor(MonoObject *p_obj) {
 	Object *instance = memnew(Object);
@@ -75,7 +77,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
 	}
 }
 
-void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_finalizer) {
+void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
 #ifdef DEBUG_ENABLED
 	CRASH_COND(p_ptr == NULL);
 	// This is only called with Reference derived classes
@@ -155,6 +157,67 @@ Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal,
 	return SignalAwaiterUtils::connect_signal_awaiter(p_source, signal, p_target, p_awaiter);
 }
 
+MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
+	List<PropertyInfo> property_list;
+	p_ptr->get_property_list(&property_list);
+
+	MonoArray *result = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), property_list.size());
+
+	int i = 0;
+	for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+		MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get().name);
+		mono_array_set(result, MonoString *, i, boxed);
+		i++;
+	}
+
+	return result;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoString *p_name, MonoArray *p_args, MonoObject **r_result) {
+	String name = GDMonoMarshal::mono_string_to_godot(p_name);
+
+	int argc = mono_array_length(p_args);
+
+	ArgumentsVector<Variant> arg_store(argc);
+	ArgumentsVector<const Variant *> args(argc);
+
+	for (int i = 0; i < argc; i++) {
+		MonoObject *elem = mono_array_get(p_args, MonoObject *, i);
+		arg_store.set(i, GDMonoMarshal::mono_object_to_variant(elem));
+		args.set(i, &arg_store.get(i));
+	}
+
+	Variant::CallError error;
+	Variant result = p_ptr->call(StringName(name), args.ptr(), argc, error);
+
+	*r_result = GDMonoMarshal::variant_to_mono_object(result);
+
+	return error.error == OK;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result) {
+	String name = GDMonoMarshal::mono_string_to_godot(p_name);
+
+	bool valid;
+	Variant value = p_ptr->get(StringName(name), &valid);
+
+	if (valid) {
+		*r_result = GDMonoMarshal::variant_to_mono_object(value);
+	}
+
+	return valid;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value) {
+	String name = GDMonoMarshal::mono_string_to_godot(p_name);
+	Variant value = GDMonoMarshal::mono_object_to_variant(p_value);
+
+	bool valid;
+	p_ptr->set(StringName(name), value, &valid);
+
+	return valid;
+}
+
 void godot_register_object_icalls() {
 	mono_add_internal_call("Godot.Object::godot_icall_Object_Ctor", (void *)godot_icall_Object_Ctor);
 	mono_add_internal_call("Godot.Object::godot_icall_Object_Disposed", (void *)godot_icall_Object_Disposed);
@@ -162,6 +225,10 @@ void godot_register_object_icalls() {
 	mono_add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", (void *)godot_icall_Object_ClassDB_get_method);
 	mono_add_internal_call("Godot.Object::godot_icall_Object_weakref", (void *)godot_icall_Object_weakref);
 	mono_add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", (void *)godot_icall_SignalAwaiter_connect);
+	mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMemberList", (void *)godot_icall_DynamicGodotObject_SetMemberList);
+	mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_InvokeMember", (void *)godot_icall_DynamicGodotObject_InvokeMember);
+	mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_GetMember", (void *)godot_icall_DynamicGodotObject_GetMember);
+	mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMember", (void *)godot_icall_DynamicGodotObject_SetMember);
 }
 
 #endif // MONO_GLUE_ENABLED

+ 11 - 1
modules/mono/glue/base_object_glue.h

@@ -42,7 +42,7 @@ Object *godot_icall_Object_Ctor(MonoObject *p_obj);
 
 void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr);
 
-void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_finalizer);
+void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer);
 
 MethodBind *godot_icall_Object_ClassDB_get_method(MonoString *p_type, MonoString *p_method);
 
@@ -50,6 +50,16 @@ MonoObject *godot_icall_Object_weakref(Object *p_obj);
 
 Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal, Object *p_target, MonoObject *p_awaiter);
 
+// DynamicGodotObject
+
+MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr);
+
+MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoString *p_name, MonoArray *p_args, MonoObject **r_result);
+
+MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result);
+
+MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value);
+
 // Register internal calls
 
 void godot_register_object_icalls();

+ 8 - 8
modules/mono/glue/collections_glue.cpp

@@ -81,7 +81,7 @@ void godot_icall_Array_Clear(Array *ptr) {
 	ptr->clear();
 }
 
-bool godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
+MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
 	return ptr->find(GDMonoMarshal::mono_object_to_variant(item)) != -1;
 }
 
@@ -113,7 +113,7 @@ void godot_icall_Array_Insert(Array *ptr, int index, MonoObject *item) {
 	ptr->insert(index, GDMonoMarshal::mono_object_to_variant(item));
 }
 
-bool godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
+MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
 	int idx = ptr->find(GDMonoMarshal::mono_object_to_variant(item));
 	if (idx >= 0) {
 		ptr->remove(idx);
@@ -208,21 +208,21 @@ void godot_icall_Dictionary_Clear(Dictionary *ptr) {
 	ptr->clear();
 }
 
-bool godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
+MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
 	// no dupes
 	Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
 	return ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value);
 }
 
-bool godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) {
+MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) {
 	return ptr->has(GDMonoMarshal::mono_object_to_variant(key));
 }
 
-bool godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
+MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
 	return ptr->erase(GDMonoMarshal::mono_object_to_variant(key));
 }
 
-bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
+MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
 	Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
 
 	// no dupes
@@ -235,7 +235,7 @@ bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject
 	return false;
 }
 
-bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
+MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
 	Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
 	if (ret == NULL) {
 		*value = NULL;
@@ -245,7 +245,7 @@ bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoOb
 	return true;
 }
 
-bool godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
+MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
 	Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
 	if (ret == NULL) {
 		*value = NULL;

+ 8 - 8
modules/mono/glue/collections_glue.h

@@ -55,7 +55,7 @@ void godot_icall_Array_Add(Array *ptr, MonoObject *item);
 
 void godot_icall_Array_Clear(Array *ptr);
 
-bool godot_icall_Array_Contains(Array *ptr, MonoObject *item);
+MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item);
 
 void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int array_index);
 
@@ -63,7 +63,7 @@ int godot_icall_Array_IndexOf(Array *ptr, MonoObject *item);
 
 void godot_icall_Array_Insert(Array *ptr, int index, MonoObject *item);
 
-bool godot_icall_Array_Remove(Array *ptr, MonoObject *item);
+MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item);
 
 void godot_icall_Array_RemoveAt(Array *ptr, int index);
 
@@ -93,17 +93,17 @@ void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *va
 
 void godot_icall_Dictionary_Clear(Dictionary *ptr);
 
-bool godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value);
+MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value);
 
-bool godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key);
+MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key);
 
-bool godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key);
+MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key);
 
-bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value);
+MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value);
 
-bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value);
+MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value);
 
-bool godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class);
+MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class);
 
 void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class);
 

+ 1 - 1
modules/mono/glue/gd_glue.cpp

@@ -175,7 +175,7 @@ MonoObject *godot_icall_GD_str2var(MonoString *p_str) {
 	return GDMonoMarshal::variant_to_mono_object(ret);
 }
 
-bool godot_icall_GD_type_exists(MonoString *p_type) {
+MonoBoolean godot_icall_GD_type_exists(MonoString *p_type) {
 	return ClassDB::class_exists(GDMonoMarshal::mono_string_to_godot(p_type));
 }
 

+ 1 - 1
modules/mono/glue/gd_glue.h

@@ -69,7 +69,7 @@ MonoString *godot_icall_GD_str(MonoArray *p_what);
 
 MonoObject *godot_icall_GD_str2var(MonoString *p_str);
 
-bool godot_icall_GD_type_exists(MonoString *p_type);
+MonoBoolean godot_icall_GD_type_exists(MonoString *p_type);
 
 MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var);
 

+ 2 - 0
modules/mono/glue/glue_header.h

@@ -74,4 +74,6 @@ void godot_register_glue_header_icalls() {
 	}                                                  \
 	Object *m_instance = ci->creation_func();
 
+#include "arguments_vector.h"
+
 #endif // MONO_GLUE_ENABLED