summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorIgnacio Etcheverry <ignalfonsore@gmail.com>2018-01-09 17:19:03 +0100
committerIgnacio Etcheverry <ignalfonsore@gmail.com>2018-01-09 17:19:03 +0100
commit5be356b72f5b765cdec069c2c4a4011a42fabc47 (patch)
tree5a8bc0f7a3e9cb0646634e5df57d9c73d98d6a09 /modules
parent52165fa12de7ca76898a7c1855a2f23797b2c2ed (diff)
Mono: Implement stack info for errors and exceptions
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript.h4
-rw-r--r--modules/mono/csharp_script.cpp72
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/glue/cs_files/DebuggingUtils.cs77
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp73
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h24
9 files changed, 251 insertions, 25 deletions
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index b5bbaa6dc9..9566e3b32e 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -349,7 +349,9 @@ public:
csi.resize(_debug_call_stack_pos);
for (int i = 0; i < _debug_call_stack_pos; i++) {
csi[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0;
- csi[_debug_call_stack_pos - i - 1].script = Ref<GDScript>(_call_stack[i].function->get_script());
+ if (_call_stack[i].function)
+ csi[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name();
+ csi[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path();
}
return csi;
}
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 949c636050..2d7583cc23 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -445,6 +445,72 @@ String CSharpLanguage::_get_indentation() const {
return "\t";
}
+Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() {
+
+ // Printing an error here will result in endless recursion, so we must be careful
+
+ if (!gdmono->is_runtime_initialized() && GDMono::get_singleton()->get_editor_tools_assembly())
+ return Vector<StackInfo>();
+
+ MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr());
+
+ MonoBoolean need_file_info = true;
+ void *ctor_args[1] = { &need_file_info };
+
+ CACHED_METHOD(System_Diagnostics_StackTrace, ctor_bool)->invoke_raw(stack_trace, ctor_args);
+
+ Vector<StackInfo> si;
+ si = stack_trace_get_info(stack_trace);
+
+ return si;
+}
+
+Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) {
+
+ // Printing an error here could result in endless recursion, so we must be careful
+
+ MonoObject *exc = NULL;
+
+ GDMonoUtils::StackTrace_GetFrames st_get_frames = CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames);
+ MonoArray *frames = st_get_frames(p_stack_trace, &exc);
+
+ if (exc) {
+ GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */);
+ return Vector<StackInfo>();
+ }
+
+ int frame_count = mono_array_length(frames);
+
+ if (frame_count <= 0)
+ return Vector<StackInfo>();
+
+ GDMonoUtils::DebugUtils_StackFrameInfo get_sf_info = CACHED_METHOD_THUNK(DebuggingUtils, GetStackFrameInfo);
+
+ Vector<StackInfo> si;
+ si.resize(frame_count);
+
+ for (int i = 0; i < frame_count; i++) {
+ StackInfo &sif = si[i];
+ MonoObject *frame = mono_array_get(frames, MonoObject *, i);
+
+ MonoString *file_name;
+ int file_line_num;
+ MonoString *method_decl;
+ get_sf_info(frame, &file_name, &file_line_num, &method_decl, &exc);
+
+ if (exc) {
+ GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */);
+ return Vector<StackInfo>();
+ }
+
+ sif.file = GDMonoMarshal::mono_string_to_godot(file_name);
+ sif.line = file_line_num;
+ sif.func = GDMonoMarshal::mono_string_to_godot(method_decl);
+ }
+
+ return si;
+}
+
void CSharpLanguage::frame() {
const Ref<MonoGCHandle> &task_scheduler_handle = GDMonoUtils::mono_cache.task_scheduler_handle;
@@ -1049,7 +1115,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
- if (top->has_method(p_method)) {
+ if (top->has_fetched_method_unknown_params(p_method)) {
return true;
}
@@ -1227,7 +1293,7 @@ ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method)
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
- GDMonoMethod *method = top->get_method(p_method);
+ GDMonoMethod *method = top->get_fetched_method_unknown_params(p_method);
if (method && !method->is_static())
return _member_get_rpc_mode(method);
@@ -1848,7 +1914,7 @@ void CSharpScript::set_source_code(const String &p_code) {
bool CSharpScript::has_method(const StringName &p_method) const {
- return script_class->has_method(p_method);
+ return script_class->has_fetched_method_unknown_params(p_method);
}
Error CSharpScript::reload(bool p_keep_state) {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 171601f3d8..3ce8a9b64e 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -303,7 +303,7 @@ public:
/* TODO */ virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
/* TODO */ virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
/* TODO */ virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { return ""; }
- /* TODO */ virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
+ virtual Vector<StackInfo> debug_get_current_stack_info();
/* PROFILING FUNCTIONS */
/* TODO */ virtual void profiling_start() {}
@@ -335,6 +335,8 @@ public:
virtual void *alloc_instance_binding_data(Object *p_object);
virtual void free_instance_binding_data(void *p_data);
+ Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
+
CSharpLanguage();
~CSharpLanguage();
};
diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/cs_files/DebuggingUtils.cs
new file mode 100644
index 0000000000..ced78f658d
--- /dev/null
+++ b/modules/mono/glue/cs_files/DebuggingUtils.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+
+namespace Godot
+{
+ internal static class DebuggingUtils
+ {
+ internal static void AppendTypeName(this StringBuilder sb, Type type)
+ {
+ if (type.IsPrimitive)
+ sb.Append(type.Name);
+ else if (type == typeof(void))
+ sb.Append("void");
+ else
+ sb.Append(type.ToString());
+
+ sb.Append(" ");
+ }
+
+ public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber, out string methodDecl)
+ {
+ fileName = frame.GetFileName();
+ fileLineNumber = frame.GetFileLineNumber();
+
+ MethodBase methodBase = frame.GetMethod();
+
+ StringBuilder sb = new StringBuilder();
+
+ if (methodBase is MethodInfo methodInfo)
+ sb.AppendTypeName(methodInfo.ReturnType);
+
+ sb.Append(methodBase.DeclaringType.FullName);
+ sb.Append(".");
+ sb.Append(methodBase.Name);
+
+ if (methodBase.IsGenericMethod)
+ {
+ Type[] genericParams = methodBase.GetGenericArguments();
+
+ sb.Append("<");
+
+ for (int j = 0; j < genericParams.Length; j++)
+ {
+ if (j > 0)
+ sb.Append(", ");
+
+ sb.AppendTypeName(genericParams[j]);
+ }
+
+ sb.Append(">");
+ }
+
+ sb.Append("(");
+
+ bool varArgs = (methodBase.CallingConvention & CallingConventions.VarArgs) != 0;
+
+ ParameterInfo[] parameter = methodBase.GetParameters();
+
+ for (int i = 0; i < parameter.Length; i++)
+ {
+ if (i > 0)
+ sb.Append(", ");
+
+ if (i == parameter.Length - 1 && varArgs)
+ sb.Append("params ");
+
+ sb.AppendTypeName(parameter[i].ParameterType);
+ }
+
+ sb.Append(")");
+
+ methodDecl = sb.ToString();
+ }
+ }
+}
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index d4df7e0cb2..6c07c90f79 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -226,7 +226,7 @@ void GDMono::initialize() {
mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL);
- OS::get_singleton()->print("Mono: ALL IS GOOD\n");
+ OS::get_singleton()->print("Mono: INITIALIZED\n");
}
#ifndef MONO_GLUE_DISABLED
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index d3315568cb..b826352f02 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -89,11 +89,6 @@ Vector<MonoClassField *> GDMonoClass::get_enum_fields() {
}
#endif
-bool GDMonoClass::has_method(const StringName &p_name) {
-
- return get_method(p_name) != NULL;
-}
-
bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) {
#ifdef DEBUG_ENABLED
@@ -225,7 +220,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base
methods_fetched = true;
}
-GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) {
+GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) {
ERR_FAIL_COND_V(!methods_fetched, NULL);
@@ -239,6 +234,11 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) {
return NULL;
}
+bool GDMonoClass::has_fetched_method_unknown_params(const StringName &p_name) {
+
+ return get_fetched_method_unknown_params(p_name) != NULL;
+}
+
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) {
MethodKey key = MethodKey(p_name, p_params_count);
@@ -303,6 +303,8 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo
MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class);
mono_method_desc_free(desc);
+ ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, NULL);
+
return get_method(method);
}
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index b6052ac0ed..f5895be144 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -112,7 +112,8 @@ public:
Vector<MonoClassField *> get_enum_fields();
#endif
- bool has_method(const StringName &p_name);
+ GDMonoMethod *get_fetched_method_unknown_params(const StringName &p_name);
+ bool has_fetched_method_unknown_params(const StringName &p_name);
bool has_attribute(GDMonoClass *p_attr_class);
MonoObject *get_attribute(GDMonoClass *p_attr_class);
@@ -120,8 +121,7 @@ public:
void fetch_attributes();
void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base);
- GDMonoMethod *get_method(const StringName &p_name);
- GDMonoMethod *get_method(const StringName &p_name, int p_params_count);
+ GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0);
GDMonoMethod *get_method(MonoMethod *p_raw_method);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count);
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index ff999b36f2..4aa2c007c2 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -31,6 +31,7 @@
#include "gd_mono_utils.h"
#include "os/dir_access.h"
+#include "os/os.h"
#include "project_settings.h"
#include "reference.h"
@@ -53,6 +54,7 @@ MonoCache mono_cache;
#define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_ns##_##m_class, m_val)
#define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val)
#define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
+#define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val)
#define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
void MonoCache::clear_members() {
@@ -72,6 +74,13 @@ void MonoCache::clear_members() {
class_String = NULL;
class_IntPtr = NULL;
+#ifdef DEBUG_ENABLED
+ class_System_Diagnostics_StackTrace = NULL;
+ methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL;
+ method_System_Diagnostics_StackTrace_ctor_bool = NULL;
+ method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL;
+#endif
+
rawclass_Dictionary = NULL;
class_Vector2 = NULL;
@@ -94,6 +103,11 @@ void MonoCache::clear_members() {
class_WeakRef = NULL;
class_MarshalUtils = NULL;
+#ifdef DEBUG_ENABLED
+ class_DebuggingUtils = NULL;
+ methodthunk_DebuggingUtils_GetStackFrameInfo = NULL;
+#endif
+
class_ExportAttribute = NULL;
field_ExportAttribute_hint = NULL;
field_ExportAttribute_hintString = NULL;
@@ -137,6 +151,13 @@ void update_corlib_cache() {
CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class()));
CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
+
+#ifdef DEBUG_ENABLED
+ CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace"));
+ CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method("GetFrames")->get_thunk());
+ CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true));
+ CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true));
+#endif
}
void update_godot_api_cache() {
@@ -161,6 +182,10 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
+#ifdef DEBUG_ENABLED
+ CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils));
+#endif
+
// Attributes
CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
@@ -183,6 +208,10 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk());
CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk());
+#ifdef DEBUG_ENABLED
+ CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk());
+#endif
+
{
/*
* TODO Right now we only support Dictionary<object, object>.
@@ -366,9 +395,47 @@ String get_exception_name_and_message(MonoObject *p_ex) {
return res;
}
-void print_unhandled_exception(MonoObject *p_ex) {
- ERR_PRINT(GDMonoUtils::get_exception_name_and_message(p_ex).utf8());
- mono_print_unhandled_exception(p_ex);
+void print_unhandled_exception(MonoObject *p_exc) {
+ print_unhandled_exception(p_exc, false);
+}
+
+void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently) {
+ mono_print_unhandled_exception(p_exc);
+#ifdef DEBUG_ENABLED
+ GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace);
+ MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr());
+
+ MonoBoolean need_file_info = true;
+ void *ctor_args[2] = { p_exc, &need_file_info };
+
+ MonoObject *unexpected_exc = NULL;
+ CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc);
+
+ if (unexpected_exc != NULL) {
+ mono_print_unhandled_exception(unexpected_exc);
+
+ if (p_fail_silently) {
+ // Called from CSharpLanguage::get_current_stack_info,
+ // so printing an error here could result in endless recursion
+ OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed");
+ return;
+ } else {
+ ERR_FAIL();
+ }
+ }
+
+ Vector<ScriptLanguage::StackInfo> si;
+ if (stack_trace != NULL)
+ si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace);
+
+ String file = si.size() ? si[0].file : __FILE__;
+ String func = si.size() ? si[0].func : FUNCTION_STR;
+ int line = si.size() ? si[0].line : __LINE__;
+ String error_msg = "Unhandled exception";
+ String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc);
+
+ ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si);
+#endif
}
} // namespace GDMonoUtils
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 284585856e..1acc547993 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -46,13 +46,10 @@ typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoO
typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray **, MonoObject **);
typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
+typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **);
+typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoObject **);
struct MonoCache {
- // Format for cached classes in the Godot namespace: class_<Class>
- // Macro: CACHED_CLASS(<Class>)
-
- // Format for cached classes in a different namespace: class_<Namespace>_<Class>
- // Macro: CACHED_NS_CLASS(<Namespace>, <Class>)
// -----------------------------------------------
// corlib classes
@@ -73,6 +70,13 @@ struct MonoCache {
GDMonoClass *class_String;
GDMonoClass *class_IntPtr;
+#ifdef DEBUG_ENABLED
+ GDMonoClass *class_System_Diagnostics_StackTrace;
+ StackTrace_GetFrames methodthunk_System_Diagnostics_StackTrace_GetFrames;
+ GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool;
+ GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool;
+#endif
+
MonoClass *rawclass_Dictionary;
// -----------------------------------------------
@@ -96,6 +100,11 @@ struct MonoCache {
GDMonoClass *class_WeakRef;
GDMonoClass *class_MarshalUtils;
+#ifdef DEBUG_ENABLED
+ GDMonoClass *class_DebuggingUtils;
+ DebugUtils_StackFrameInfo methodthunk_DebuggingUtils_GetStackFrameInfo;
+#endif
+
GDMonoClass *class_ExportAttribute;
GDMonoField *field_ExportAttribute_hint;
GDMonoField *field_ExportAttribute_hintString;
@@ -167,7 +176,8 @@ MonoDomain *create_domain(const String &p_friendly_name);
String get_exception_name_and_message(MonoObject *p_ex);
-void print_unhandled_exception(MonoObject *p_ex);
+void print_unhandled_exception(MonoObject *p_exc);
+void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently);
} // namespace GDMonoUtils
@@ -175,9 +185,9 @@ void print_unhandled_exception(MonoObject *p_ex);
#define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class)
#define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_mono_ptr())
-#define CACHED_NS_CLASS(m_ns, m_class) (GDMonoUtils::mono_cache.class_##m_ns##_##m_class)
#define CACHED_RAW_MONO_CLASS(m_class) (GDMonoUtils::mono_cache.rawclass_##m_class)
#define CACHED_FIELD(m_class, m_field) (GDMonoUtils::mono_cache.field_##m_class##_##m_field)
+#define CACHED_METHOD(m_class, m_method) (GDMonoUtils::mono_cache.method_##m_class##_##m_method)
#define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method)
#ifdef REAL_T_IS_DOUBLE