Merge pull request #27497 from neikeq/dynamicmetaobject

C#: Add DynamicGodotObject class
This commit is contained in:
Ignacio Roldán Etcheverry 2019-03-29 02:15:56 +01:00 committed by GitHub
commit 805eec7643
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 407 additions and 34 deletions

View file

@ -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

View file

@ -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
}
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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);

View file

@ -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));
}

View file

@ -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);

View file

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