1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

Re-write mono module editor code in C#

Make the build system automatically build the C# Api assemblies to be shipped with the editor.
Make the editor, editor player and debug export templates use Api assemblies built with debug symbols.
Always run MSBuild to build the editor tools and Api assemblies when building Godot.
Several bugs fixed related to assembly hot reloading and restoring state.
Fix StringExtensions internal calls not being registered correctly, resulting in MissingMethodException.
This commit is contained in:
Ignacio Etcheverry
2019-07-03 09:44:53 +02:00
parent 7b569e91c0
commit 270af6fa08
93 changed files with 5694 additions and 4122 deletions

View File

@@ -125,6 +125,7 @@ void MonoCache::clear_godot_api_cache() {
class_Array = NULL;
class_Dictionary = NULL;
class_MarshalUtils = NULL;
class_ISerializationListener = NULL;
#ifdef DEBUG_ENABLED
class_DebuggingUtils = NULL;
@@ -242,6 +243,7 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(Array, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array));
CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary));
CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
CACHE_CLASS_AND_CHECK(ISerializationListener, GODOT_API_CLASS(ISerializationListener));
#ifdef DEBUG_ENABLED
CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils));
@@ -302,7 +304,7 @@ void update_godot_api_cache() {
#endif
// TODO Move to CSharpLanguage::init() and do handle disposal
MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
MonoObject *task_scheduler = mono_object_new(mono_domain_get(), GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
GDMonoUtils::runtime_object_init(task_scheduler, GODOT_API_CLASS(GodotTaskScheduler));
mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
@@ -371,7 +373,6 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
// This way if the unmanaged world has no references to our owner
// but the managed instance is alive, the refcount will be 1 instead of 0.
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
ref->reference();
}
@@ -384,7 +385,7 @@ void set_main_thread(MonoThread *p_thread) {
void attach_current_thread() {
ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
MonoThread *mono_thread = mono_thread_attach(SCRIPTS_DOMAIN);
MonoThread *mono_thread = mono_thread_attach(mono_domain_get());
ERR_FAIL_NULL(mono_thread);
}
@@ -448,17 +449,12 @@ GDMonoClass *get_class_native_base(GDMonoClass *p_class) {
}
MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) {
String object_type = p_object->get_class_name();
if (object_type[0] == '_')
object_type = object_type.substr(1, object_type.length());
if (!ClassDB::is_parent_class(object_type, p_native)) {
if (!ClassDB::is_parent_class(p_object->get_class_name(), p_native)) {
ERR_EXPLAIN("Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'");
ERR_FAIL_V(NULL);
}
MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
ERR_FAIL_NULL_V(mono_object, NULL);
CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
@@ -470,7 +466,7 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa
}
MonoObject *create_managed_from(const NodePath &p_from) {
MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(NodePath));
MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(NodePath));
ERR_FAIL_NULL_V(mono_object, NULL);
// Construct
@@ -482,7 +478,7 @@ MonoObject *create_managed_from(const NodePath &p_from) {
}
MonoObject *create_managed_from(const RID &p_from) {
MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(RID));
MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(RID));
ERR_FAIL_NULL_V(mono_object, NULL);
// Construct
@@ -494,7 +490,7 @@ MonoObject *create_managed_from(const RID &p_from) {
}
MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) {
MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
ERR_FAIL_NULL_V(mono_object, NULL);
// Search constructor that takes a pointer as parameter
@@ -518,13 +514,13 @@ MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) {
MonoException *exc = NULL;
GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
return mono_object;
}
MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) {
MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
ERR_FAIL_NULL_V(mono_object, NULL);
// Search constructor that takes a pointer as parameter
@@ -548,7 +544,7 @@ MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class)
MonoException *exc = NULL;
GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
return mono_object;
}
@@ -667,7 +663,10 @@ void print_unhandled_exception(MonoException *p_exc) {
}
void set_pending_exception(MonoException *p_exc) {
#ifdef HAS_PENDING_EXCEPTIONS
#ifdef NO_PENDING_EXCEPTIONS
debug_unhandled_exception(p_exc);
GD_UNREACHABLE();
#else
if (get_runtime_invoke_count() == 0) {
debug_unhandled_exception(p_exc);
GD_UNREACHABLE();
@@ -677,9 +676,6 @@ void set_pending_exception(MonoException *p_exc) {
ERR_PRINTS("Exception thrown from managed code, but it could not be set as pending:");
GDMonoUtils::debug_print_unhandled_exception(p_exc);
}
#else
debug_unhandled_exception(p_exc);
GD_UNREACHABLE();
#endif
}
@@ -755,113 +751,137 @@ void dispose(MonoObject *p_mono_object, MonoException **r_exc) {
namespace Marshal {
MonoBoolean type_is_generic_array(MonoReflectionType *p_reftype) {
#ifdef MONO_GLUE_ENABLED
#ifdef TOOLS_ENABLED
#define NO_GLUE_RET(m_ret) \
{ \
if (!mono_cache.godot_api_cache_updated) return m_ret; \
}
#else
#define NO_GLUE_RET(m_ret) \
{}
#endif
#else
#define NO_GLUE_RET(m_ret) \
{ return m_ret; }
#endif
bool type_is_generic_array(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
TypeIsGenericArray thunk = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return res;
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
MonoBoolean type_is_generic_dictionary(MonoReflectionType *p_reftype) {
bool type_is_generic_dictionary(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
TypeIsGenericDictionary thunk = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return res;
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) {
ArrayGetElementType thunk = CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType);
MonoException *exc = NULL;
invoke_method_thunk(thunk, p_array_reftype, r_elem_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
}
void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
DictionaryGetKeyValueTypes thunk = CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes);
MonoException *exc = NULL;
invoke_method_thunk(thunk, p_dict_reftype, r_key_reftype, r_value_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
}
MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) {
bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
GenericIEnumerableIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType);
MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return res;
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) {
bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
GenericIDictionaryIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType);
MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return res;
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) {
bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) {
NO_GLUE_RET(false);
GenericIEnumerableIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info);
MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_elem_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return res;
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
NO_GLUE_RET(false);
GenericIDictionaryIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info);
MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_key_reftype, r_value_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return res;
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
Array enumerable_to_array(MonoObject *p_enumerable) {
NO_GLUE_RET(Array());
Array result;
EnumerableToArray thunk = CACHED_METHOD_THUNK(MarshalUtils, EnumerableToArray);
MonoException *exc = NULL;
invoke_method_thunk(thunk, p_enumerable, &result, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
return result;
}
Dictionary idictionary_to_dictionary(MonoObject *p_idictionary) {
NO_GLUE_RET(Dictionary());
Dictionary result;
IDictionaryToDictionary thunk = CACHED_METHOD_THUNK(MarshalUtils, IDictionaryToDictionary);
MonoException *exc = NULL;
invoke_method_thunk(thunk, p_idictionary, &result, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
return result;
}
Dictionary generic_idictionary_to_dictionary(MonoObject *p_generic_idictionary) {
NO_GLUE_RET(Dictionary());
Dictionary result;
GenericIDictionaryToDictionary thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryToDictionary);
MonoException *exc = NULL;
invoke_method_thunk(thunk, p_generic_idictionary, &result, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
return result;
}
GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype) {
NO_GLUE_RET(NULL);
MakeGenericArrayType thunk = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericArrayType);
MonoException *exc = NULL;
MonoReflectionType *reftype = invoke_method_thunk(thunk, p_elem_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
}
GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) {
NO_GLUE_RET(NULL);
MakeGenericDictionaryType thunk = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericDictionaryType);
MonoException *exc = NULL;
MonoReflectionType *reftype = invoke_method_thunk(thunk, p_key_reftype, p_value_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
UNHANDLED_EXCEPTION(exc);
return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
}
} // namespace Marshal
// namespace Marshal
} // namespace GDMonoUtils