Browse Source

C#: Support type hints for exported Arrays

Added the code for Dictionary as well, but it's not yet supported by the Godot inspector.
Ignacio Etcheverry 6 years ago
parent
commit
480d4c6fba

+ 8 - 1
modules/mono/csharp_script.cpp

@@ -2166,7 +2166,8 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_
 		CRASH_NOW();
 		CRASH_NOW();
 	}
 	}
 
 
-	Variant::Type variant_type = GDMonoMarshal::managed_to_variant_type(type);
+	GDMonoMarshal::ExportInfo export_info;
+	Variant::Type variant_type = GDMonoMarshal::managed_to_variant_type(type, &export_info);
 
 
 	if (!p_member->has_attribute(CACHED_CLASS(ExportAttribute))) {
 	if (!p_member->has_attribute(CACHED_CLASS(ExportAttribute))) {
 		r_prop_info = PropertyInfo(variant_type, name.operator String(), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE);
 		r_prop_info = PropertyInfo(variant_type, name.operator String(), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE);
@@ -2191,6 +2192,7 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_
 		ERR_PRINTS("Unknown type of exported member: " + p_class->get_full_name() + "." + name.operator String());
 		ERR_PRINTS("Unknown type of exported member: " + p_class->get_full_name() + "." + name.operator String());
 		return false;
 		return false;
 	} else if (variant_type == Variant::INT && type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(type.type_class->get_mono_ptr())) {
 	} else if (variant_type == Variant::INT && type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(type.type_class->get_mono_ptr())) {
+		// TODO: Move to ExportInfo?
 		variant_type = Variant::INT;
 		variant_type = Variant::INT;
 		hint = PROPERTY_HINT_ENUM;
 		hint = PROPERTY_HINT_ENUM;
 
 
@@ -2257,6 +2259,11 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_
 
 
 		hint = PROPERTY_HINT_RESOURCE_TYPE;
 		hint = PROPERTY_HINT_RESOURCE_TYPE;
 		hint_string = NATIVE_GDMONOCLASS_NAME(field_native_class);
 		hint_string = NATIVE_GDMONOCLASS_NAME(field_native_class);
+	} else if (variant_type == Variant::ARRAY && export_info.array.element_type != Variant::NIL) {
+		hint = PROPERTY_HINT_TYPE_STRING;
+		hint_string = itos(export_info.array.element_type) + ":";
+	} else if (variant_type == Variant::DICTIONARY && export_info.dictionary.key_type != Variant::NIL && export_info.dictionary.value_type != Variant::NIL) {
+		// TODO: There is no hint for this yet
 	} else {
 	} else {
 		hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr));
 		hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr));
 		hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr);
 		hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr);

+ 14 - 0
modules/mono/glue/Managed/Files/MarshalUtils.cs

@@ -18,6 +18,20 @@ namespace Godot
             return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
             return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
         }
         }
 
 
+        static void ArrayGetElementType(Type type, out Type elementType)
+        {
+            elementType = type.GetGenericArguments()[0];
+        }
+
+        static void DictionaryGetKeyValueTypes(Type type, out Type keyType, out Type valueType)
+        {
+            var genericArgs = type.GetGenericArguments();
+
+            keyType = genericArgs[0];
+            valueType = genericArgs[1];
+        }
+
+        // TODO Add support for IEnumerable<T> and IDictionary<TKey, TValue>
         // TODO: EnumerableToArray and IDictionaryToDictionary can be optimized
         // TODO: EnumerableToArray and IDictionaryToDictionary can be optimized
 
 
         internal static void EnumerableToArray(IEnumerable enumerable, IntPtr godotArrayPtr)
         internal static void EnumerableToArray(IEnumerable enumerable, IntPtr godotArrayPtr)

+ 2 - 1
modules/mono/mono_gd/gd_mono_class.cpp

@@ -55,7 +55,8 @@ String GDMonoClass::get_full_name() const {
 }
 }
 
 
 MonoType *GDMonoClass::get_mono_type() {
 MonoType *GDMonoClass::get_mono_type() {
-	// Care, you cannot compare MonoType pointers
+	// Careful, you cannot compare two MonoType*.
+	// There is mono_metadata_type_equal, how is this different from comparing two MonoClass*?
 	return get_mono_type(mono_class);
 	return get_mono_type(mono_class);
 }
 }
 
 

+ 2 - 2
modules/mono/mono_gd/gd_mono_field.cpp

@@ -435,7 +435,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
 			MonoException *exc = NULL;
 			MonoException *exc = NULL;
 
 
 			GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
 			GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
-			MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, &exc);
+			MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 			if (is_dict) {
 			if (is_dict) {
@@ -447,7 +447,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
 			exc = NULL;
 			exc = NULL;
 
 
 			GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
 			GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
-			MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, &exc);
+			MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 			if (is_array) {
 			if (is_array) {

+ 3 - 15
modules/mono/mono_gd/gd_mono_header.h

@@ -35,24 +35,12 @@
 
 
 class GDMonoAssembly;
 class GDMonoAssembly;
 class GDMonoClass;
 class GDMonoClass;
-class IMonoClassMember;
 class GDMonoField;
 class GDMonoField;
-class GDMonoProperty;
 class GDMonoMethod;
 class GDMonoMethod;
+class GDMonoProperty;
 
 
-struct ManagedType {
-	int type_encoding;
-	GDMonoClass *type_class;
-
-	ManagedType() :
-			type_encoding(0),
-			type_class(NULL) {
-	}
+class IMonoClassMember;
 
 
-	ManagedType(int p_type_encoding, GDMonoClass *p_type_class) :
-			type_encoding(p_type_encoding),
-			type_class(p_type_class) {
-	}
-};
+#include "managed_type.h"
 
 
 #endif // GD_MONO_HEADER_H
 #endif // GD_MONO_HEADER_H

+ 33 - 15
modules/mono/mono_gd/gd_mono_marshal.cpp

@@ -35,7 +35,7 @@
 
 
 namespace GDMonoMarshal {
 namespace GDMonoMarshal {
 
 
-Variant::Type managed_to_variant_type(const ManagedType &p_type) {
+Variant::Type managed_to_variant_type(const ManagedType &p_type, ExportInfo *r_export_info) {
 	switch (p_type.type_encoding) {
 	switch (p_type.type_encoding) {
 		case MONO_TYPE_BOOLEAN:
 		case MONO_TYPE_BOOLEAN:
 			return Variant::BOOL;
 			return Variant::BOOL;
@@ -171,19 +171,43 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
 
 
 			MonoException *exc = NULL;
 			MonoException *exc = NULL;
 			GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
 			GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
-			MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, &exc);
+			MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 			if (is_dict) {
 			if (is_dict) {
+				if (r_export_info) {
+					MonoReflectionType *key_reftype;
+					MonoReflectionType *value_reftype;
+
+					exc = NULL;
+					invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes),
+							reftype, &key_reftype, &value_reftype, &exc);
+					UNLIKELY_UNHANDLED_EXCEPTION(exc);
+
+					r_export_info->dictionary.key_type = managed_to_variant_type(ManagedType::from_reftype(key_reftype));
+					r_export_info->dictionary.value_type = managed_to_variant_type(ManagedType::from_reftype(value_reftype));
+				}
+
 				return Variant::DICTIONARY;
 				return Variant::DICTIONARY;
 			}
 			}
 
 
 			exc = NULL;
 			exc = NULL;
 			GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
 			GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
-			MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, &exc);
+			MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 			if (is_array) {
 			if (is_array) {
+				if (r_export_info) {
+					MonoReflectionType *elem_reftype;
+
+					exc = NULL;
+					invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType),
+							reftype, &elem_reftype, &exc);
+					UNLIKELY_UNHANDLED_EXCEPTION(exc);
+
+					r_export_info->array.element_type = managed_to_variant_type(ManagedType::from_reftype(elem_reftype));
+				}
+
 				return Variant::ARRAY;
 				return Variant::ARRAY;
 			}
 			}
 
 
@@ -573,7 +597,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
 
 
 				MonoException *exc = NULL;
 				MonoException *exc = NULL;
 				GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
 				GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
-				MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, &exc);
+				MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
 				UNLIKELY_UNHANDLED_EXCEPTION(exc);
 				UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 				if (is_dict) {
 				if (is_dict) {
@@ -582,7 +606,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
 
 
 				exc = NULL;
 				exc = NULL;
 				GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
 				GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
-				MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, &exc);
+				MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
 				UNLIKELY_UNHANDLED_EXCEPTION(exc);
 				UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 				if (is_array) {
 				if (is_array) {
@@ -609,15 +633,9 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
 	if (!p_obj)
 	if (!p_obj)
 		return Variant();
 		return Variant();
 
 
-	GDMonoClass *tclass = GDMono::get_singleton()->get_class(mono_object_get_class(p_obj));
-	ERR_FAIL_COND_V(!tclass, Variant());
-
-	MonoType *raw_type = tclass->get_mono_type();
-
-	ManagedType type;
+	ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj));
 
 
-	type.type_encoding = mono_type_get_type(raw_type);
-	type.type_class = tclass;
+	ERR_FAIL_COND_V(!type.type_class, Variant());
 
 
 	switch (type.type_encoding) {
 	switch (type.type_encoding) {
 		case MONO_TYPE_BOOLEAN:
 		case MONO_TYPE_BOOLEAN:
@@ -784,7 +802,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
 			MonoException *exc = NULL;
 			MonoException *exc = NULL;
 
 
 			GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
 			GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
-			MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, &exc);
+			MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 			if (is_dict) {
 			if (is_dict) {
@@ -797,7 +815,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
 			exc = NULL;
 			exc = NULL;
 
 
 			GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
 			GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
-			MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, &exc);
+			MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 			UNLIKELY_UNHANDLED_EXCEPTION(exc);
 
 
 			if (is_array) {
 			if (is_array) {

+ 20 - 1
modules/mono/mono_gd/gd_mono_marshal.h

@@ -32,6 +32,7 @@
 #define GDMONOMARSHAL_H
 #define GDMONOMARSHAL_H
 
 
 #include "core/variant.h"
 #include "core/variant.h"
+
 #include "gd_mono.h"
 #include "gd_mono.h"
 #include "gd_mono_utils.h"
 #include "gd_mono_utils.h"
 
 
@@ -56,7 +57,25 @@ T unbox(MonoObject *p_obj) {
 #define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x)
 #define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x)
 #define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x)
 #define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x)
 
 
-Variant::Type managed_to_variant_type(const ManagedType &p_type);
+// FIXME: Made this struct in a hurry. It could be done differently.
+struct ExportInfo {
+	struct ArrayInfo {
+		Variant::Type element_type;
+
+		ArrayInfo() :
+				element_type(Variant::NIL) {}
+	} array;
+	struct DictionaryInfo {
+		Variant::Type key_type;
+		Variant::Type value_type;
+
+		DictionaryInfo() :
+				key_type(Variant::NIL),
+				value_type(Variant::NIL) {}
+	} dictionary;
+};
+
+Variant::Type managed_to_variant_type(const ManagedType &p_type, ExportInfo *r_export_info = NULL);
 
 
 // String
 // String
 
 

+ 4 - 0
modules/mono/mono_gd/gd_mono_utils.cpp

@@ -153,6 +153,8 @@ void MonoCache::clear_members() {
 
 
 	methodthunk_MarshalUtils_TypeIsGenericArray = NULL;
 	methodthunk_MarshalUtils_TypeIsGenericArray = NULL;
 	methodthunk_MarshalUtils_TypeIsGenericDictionary = NULL;
 	methodthunk_MarshalUtils_TypeIsGenericDictionary = NULL;
+	methodthunk_MarshalUtils_ArrayGetElementType = NULL;
+	methodthunk_MarshalUtils_DictionaryGetKeyValueTypes = NULL;
 	methodthunk_MarshalUtils_EnumerableToArray = NULL;
 	methodthunk_MarshalUtils_EnumerableToArray = NULL;
 	methodthunk_MarshalUtils_IDictionaryToDictionary = NULL;
 	methodthunk_MarshalUtils_IDictionaryToDictionary = NULL;
 
 
@@ -258,6 +260,8 @@ void update_godot_api_cache() {
 
 
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, (TypeIsGenericArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericArray", 1));
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, (TypeIsGenericArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericArray", 1));
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericDictionary, (TypeIsGenericDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericDictionary", 1));
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericDictionary, (TypeIsGenericDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericDictionary", 1));
+	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
+	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, EnumerableToArray, (EnumerableToArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("EnumerableToArray", 2));
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, EnumerableToArray, (EnumerableToArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("EnumerableToArray", 2));
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IDictionaryToDictionary, (IDictionaryToDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IDictionaryToDictionary", 2));
 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IDictionaryToDictionary, (IDictionaryToDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IDictionaryToDictionary", 2));
 
 

+ 6 - 2
modules/mono/mono_gd/gd_mono_utils.h

@@ -58,8 +58,10 @@ typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoException *
 typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoException **);
 typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoException **);
 typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoException **);
 typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoException **);
 
 
-typedef MonoBoolean (*TypeIsGenericArray)(MonoObject *, MonoException **);
-typedef MonoBoolean (*TypeIsGenericDictionary)(MonoObject *, MonoException **);
+typedef MonoBoolean (*TypeIsGenericArray)(MonoReflectionType *, MonoException **);
+typedef MonoBoolean (*TypeIsGenericDictionary)(MonoReflectionType *, MonoException **);
+typedef MonoBoolean (*ArrayGetElementType)(MonoReflectionType *, MonoReflectionType **, MonoException **);
+typedef MonoBoolean (*DictionaryGetKeyValueTypes)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **);
 typedef void (*EnumerableToArray)(MonoObject *, Array *, MonoException **);
 typedef void (*EnumerableToArray)(MonoObject *, Array *, MonoException **);
 typedef void (*IDictionaryToDictionary)(MonoObject *, Dictionary *, MonoException **);
 typedef void (*IDictionaryToDictionary)(MonoObject *, Dictionary *, MonoException **);
 
 
@@ -156,6 +158,8 @@ struct MonoCache {
 
 
 	TypeIsGenericArray methodthunk_MarshalUtils_TypeIsGenericArray;
 	TypeIsGenericArray methodthunk_MarshalUtils_TypeIsGenericArray;
 	TypeIsGenericDictionary methodthunk_MarshalUtils_TypeIsGenericDictionary;
 	TypeIsGenericDictionary methodthunk_MarshalUtils_TypeIsGenericDictionary;
+	ArrayGetElementType methodthunk_MarshalUtils_ArrayGetElementType;
+	DictionaryGetKeyValueTypes methodthunk_MarshalUtils_DictionaryGetKeyValueTypes;
 	EnumerableToArray methodthunk_MarshalUtils_EnumerableToArray;
 	EnumerableToArray methodthunk_MarshalUtils_EnumerableToArray;
 	IDictionaryToDictionary methodthunk_MarshalUtils_IDictionaryToDictionary;
 	IDictionaryToDictionary methodthunk_MarshalUtils_IDictionaryToDictionary;
 
 

+ 58 - 0
modules/mono/mono_gd/managed_type.cpp

@@ -0,0 +1,58 @@
+/*************************************************************************/
+/*  managed_type.cpp                                                     */
+/*************************************************************************/
+/*                       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.                */
+/*************************************************************************/
+
+#include "managed_type.h"
+
+#include "gd_mono.h"
+#include "gd_mono_class.h"
+
+ManagedType ManagedType::from_class(GDMonoClass *p_class) {
+	return ManagedType(mono_type_get_type(p_class->get_mono_type()), p_class);
+}
+
+ManagedType ManagedType::from_class(MonoClass *p_mono_class) {
+	GDMonoClass *tclass = GDMono::get_singleton()->get_class(p_mono_class);
+	ERR_FAIL_COND_V(!tclass, ManagedType());
+
+	return ManagedType(mono_type_get_type(tclass->get_mono_type()), tclass);
+}
+
+ManagedType ManagedType::from_type(MonoType *p_mono_type) {
+	MonoClass *mono_class = mono_class_from_mono_type(p_mono_type);
+	GDMonoClass *tclass = GDMono::get_singleton()->get_class(mono_class);
+	ERR_FAIL_COND_V(!tclass, ManagedType());
+
+	return ManagedType(mono_type_get_type(p_mono_type), tclass);
+}
+
+ManagedType ManagedType::from_reftype(MonoReflectionType *p_mono_reftype) {
+	MonoType *mono_type = mono_reflection_type_get_type(p_mono_reftype);
+	return from_type(mono_type);
+}

+ 58 - 0
modules/mono/mono_gd/managed_type.h

@@ -0,0 +1,58 @@
+/*************************************************************************/
+/*  managed_type.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 MANAGED_TYPE_H
+#define MANAGED_TYPE_H
+
+#include <mono/metadata/object.h>
+
+#include "gd_mono_header.h"
+
+struct ManagedType {
+	int type_encoding;
+	GDMonoClass *type_class;
+
+	static ManagedType from_class(GDMonoClass *p_class);
+	static ManagedType from_class(MonoClass *p_mono_class);
+	static ManagedType from_type(MonoType *p_mono_type);
+	static ManagedType from_reftype(MonoReflectionType *p_mono_reftype);
+
+	ManagedType() :
+			type_encoding(0),
+			type_class(NULL) {
+	}
+
+	ManagedType(int p_type_encoding, GDMonoClass *p_type_class) :
+			type_encoding(p_type_encoding),
+			type_class(p_type_class) {
+	}
+};
+
+#endif // MANAGED_TYPE_H