Example #1
0
MonoException *
mono_get_exception_reflection_type_load_checked (MonoArray *types, MonoArray *exceptions, MonoError *error)
{
	MonoClass *klass;
	gpointer args [2];
	MonoObject *exc;
	MonoMethod *method;
	gpointer iter;

	klass = mono_class_load_from_name (mono_get_corlib (), "System.Reflection", "ReflectionTypeLoadException");

	mono_class_init (klass);

	/* Find the Type[], Exception[] ctor */
	iter = NULL;
	while ((method = mono_class_get_methods (klass, &iter))) {
		if (!strcmp (".ctor", mono_method_get_name (method))) {
			MonoMethodSignature *sig = mono_method_signature (method);

			if (sig->param_count == 2 && sig->params [0]->type == MONO_TYPE_SZARRAY && sig->params [1]->type == MONO_TYPE_SZARRAY)
				break;
		}
		method = NULL;
	}
	g_assert (method);

	args [0] = types;
	args [1] = exceptions;

	exc = mono_object_new_checked (mono_domain_get (), klass, error);
	mono_error_assert_ok (error);

	mono_runtime_invoke_checked (method, exc, args, error);
	return_val_if_nok (error, NULL);

	return (MonoException *) exc;
}
Example #2
0
/**
 * mono_get_exception_type_initialization:
 * @type_name: the name of the type that failed to initialize.
 * @inner: the inner exception.
 *
 * Returns: a new instance of the `System.TypeInitializationException`
 */
MonoException *
mono_get_exception_type_initialization (const gchar *type_name, MonoException *inner)
{
	MonoError error;
	MonoClass *klass;
	gpointer args [2];
	MonoObject *exc;
	MonoMethod *method;
	gpointer iter;

	klass = mono_class_load_from_name (mono_get_corlib (), "System", "TypeInitializationException");

	mono_class_init (klass);

	iter = NULL;
	while ((method = mono_class_get_methods (klass, &iter))) {
		if (!strcmp (".ctor", mono_method_get_name (method))) {
			MonoMethodSignature *sig = mono_method_signature (method);

			if (sig->param_count == 2 && sig->params [0]->type == MONO_TYPE_STRING && mono_class_from_mono_type (sig->params [1]) == mono_defaults.exception_class)
				break;
		}
		method = NULL;
	}
	g_assert (method);

	args [0] = mono_string_new (mono_domain_get (), type_name);
	args [1] = inner;

	exc = mono_object_new_checked (mono_domain_get (), klass, &error);
	mono_error_assert_ok (&error);
	mono_runtime_invoke_checked (method, exc, args, &error);
	mono_error_raise_exception (&error); /* FIXME don't raise here */

	return (MonoException *) exc;
}
Example #3
0
void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base) {

	CRASH_COND(!CACHED_CLASS(GodotObject)->is_assignable_from(this));

	if (methods_fetched)
		return;

	void *iter = NULL;
	MonoMethod *raw_method = NULL;
	while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) {
		StringName name = mono_method_get_name(raw_method);

		// get_method implicitly fetches methods and adds them to this->methods
		GDMonoMethod *method = get_method(raw_method, name);
		ERR_CONTINUE(!method);

		if (method->get_name() != name) {

#ifdef DEBUG_ENABLED
			String fullname = method->get_ret_type_full_name() + " " + name + "(" + method->get_signature_desc(true) + ")";
			WARN_PRINTS("Method `" + fullname + "` is hidden by Godot API method. Should be `" +
						method->get_full_name_no_class() + "`. In class `" + namespace_name + "." + class_name + "`.");
#endif
			continue;
		}

#ifdef DEBUG_ENABLED
		// For debug builds, we also fetched from native base classes as well before if this is not a native base class.
		// This allows us to warn the user here if he is using snake_case by mistake.

		if (p_native_base != this) {

			GDMonoClass *native_top = p_native_base;
			while (native_top) {
				GDMonoMethod *m = native_top->get_method(name, method->get_parameters_count());

				if (m && m->get_name() != name) {
					// found
					String fullname = m->get_ret_type_full_name() + " " + name + "(" + m->get_signature_desc(true) + ")";
					WARN_PRINTS("Method `" + fullname + "` should be `" + m->get_full_name_no_class() +
								"`. In class `" + namespace_name + "." + class_name + "`.");
					break;
				}

				if (native_top == CACHED_CLASS(GodotObject))
					break;

				native_top = native_top->get_parent_class();
			}
		}
#endif

		uint32_t flags = mono_method_get_flags(method->mono_method, NULL);

		if (!(flags & MONO_METHOD_ATTR_VIRTUAL))
			continue;

		// Virtual method of Godot Object derived type, let's try to find GodotMethod attribute

		GDMonoClass *top = p_native_base;

		while (top) {
			GDMonoMethod *base_method = top->get_method(name, method->get_parameters_count());

			if (base_method && base_method->has_attribute(CACHED_CLASS(GodotMethodAttribute))) {
				// Found base method with GodotMethod attribute.
				// We get the original API method name from this attribute.
				// This name must point to the virtual method.

				MonoObject *attr = base_method->get_attribute(CACHED_CLASS(GodotMethodAttribute));

				StringName godot_method_name = CACHED_FIELD(GodotMethodAttribute, methodName)->get_string_value(attr);
#ifdef DEBUG_ENABLED
				CRASH_COND(godot_method_name == StringName());
#endif
				MethodKey key = MethodKey(godot_method_name, method->get_parameters_count());
				GDMonoMethod **existing_method = methods.getptr(key);
				if (existing_method)
					memdelete(*existing_method); // Must delete old one
				methods.set(key, method);

				break;
			}

			if (top == CACHED_CLASS(GodotObject))
				break;

			top = top->get_parent_class();
		}
	}

	methods_fetched = true;
}
Example #4
0
void
virt_mono_throw_unhandled_exception (MonoObject *exc)
{
  caddr_t err;
  char *message = (char *) "";
  const char *name = (const char *) "";
  MonoString *str;
  MonoMethod *method;
  MonoClass *klass;
  gboolean free_message = FALSE;
  gint i;

  if (mono_object_isinst (exc, mono_get_exception_class ()))
    {
      klass = mono_object_get_class (exc);
      method = NULL;
      while (klass && method == NULL)
	{
	  gpointer m_iter = NULL;
	  for (method = mono_class_get_methods (klass, &m_iter); method != NULL;
	      method = mono_class_get_methods (klass, &m_iter))
	    {
	      MonoMethodSignature *sig = mono_method_signature (method);
	      guint32 flags = 0;
	      const char *name = mono_method_get_name (method);

	      mono_method_get_flags (method, &flags);
	      if (!strcmp ("ToString", name) &&
		  sig->param_count == 0
#ifdef OLD_KIT_1_1_5
		  && (flags & METHOD_ATTRIBUTE_VIRTUAL)
		  && (flags & METHOD_ATTRIBUTE_PUBLIC)
#endif
		  )
		{
		  break;
		}
	      method = NULL;
	    }

	  if (method == NULL)
	    klass = mono_class_get_parent (klass);
	}

      g_assert (method);

      str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
      if (str) {
	message = mono_string_to_utf8 (str);
	free_message = TRUE;
	name = mono_class_get_name (klass);
      }
    }

  /*
   * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
   *	   exc->vtable->klass->name, message);
   */
  g_printerr ("\nUnhandled Exception: %s\n", message);


  err = srv_make_new_error ("42000", "MN001", "Unhandled Mono Exception [%.200s]: %.200s",
      name, message);
  if (free_message)
    g_free (message);
  sqlr_resignal (err);
}
Example #5
0
IMonoMethod *CScriptClass::GetMethod(const char *name, IMonoArray *pArgs, bool throwOnFail)
{
	MonoMethodSignature *pSignature = nullptr;

	void *pIterator = 0;

	MonoClass *pClass = (MonoClass *)m_pObject;
	MonoType *pClassType = mono_class_get_type(pClass);
	MonoMethod *pCurMethod = nullptr;

	int suppliedArgsCount = pArgs ? pArgs->GetSize() : 0;

	while (pClass != nullptr)
	{
		pCurMethod = mono_class_get_methods(pClass, &pIterator);
		if(pCurMethod == nullptr)
		{
			pClass = mono_class_get_parent(pClass);
			if(pClass == mono_get_object_class())
				break;

			pIterator = 0;
			continue;
		}

		pSignature = mono_method_signature(pCurMethod);
		int signatureParamCount = mono_signature_get_param_count(pSignature);

		bool bCorrectName = !strcmp(mono_method_get_name(pCurMethod), name);
		if(bCorrectName && signatureParamCount == 0 && suppliedArgsCount == 0)
			return new CScriptMethod(pCurMethod);
		else if(bCorrectName && signatureParamCount >= suppliedArgsCount && suppliedArgsCount != 0)
		{
			//if(bStatic != (mono_method_get_flags(pCurMethod, nullptr) & METHOD_ATTRIBUTE_STATIC) > 0)
				//continue;

			void *pIter = nullptr;

			MonoType *pType = nullptr;
			for(int i = 0; i < signatureParamCount; i++)
			{
				pType = mono_signature_get_params(pSignature, &pIter);

				if(mono::object item = pArgs->GetItem(i))
				{
					MonoClass *pItemClass = mono_object_get_class((MonoObject *)item);
					MonoType *pItemType = mono_class_get_type(pItemClass);

					MonoTypeEnum itemMonoType = (MonoTypeEnum)mono_type_get_type(pItemType);

					MonoTypeEnum monoType = (MonoTypeEnum)mono_type_get_type(pType);

					if(itemMonoType != monoType)
					{
						// exceptions:
						// Anything can be treated as object.
						if(monoType == MONO_TYPE_OBJECT) {}
						// The runtime confuses things with value types a lot, so ignore parameters that appear with that type.
						else if(itemMonoType == MONO_TYPE_VALUETYPE || monoType == MONO_TYPE_VALUETYPE) {}
						else
						{
							if(MonoClass *pMethodParameterClass = mono_type_get_class(pType))
							{
								MonoWarning("Parameter mismatch when searching for method %s in class %s.%s, on parameter %i: Provided type %s.%s does not match expected parameter type %s.%s.", 
									name, mono_class_get_namespace(pClass), mono_class_get_name(pClass), i + 1, mono_class_get_namespace(pItemClass), mono_class_get_name(pItemClass), mono_class_get_namespace(pMethodParameterClass), mono_class_get_name(pMethodParameterClass));
							}
							else
							{
								MonoWarning("Parameter mismatch when searching for method %s in class %s.%s, on parameter %i: Provided type %s.%s does not match parameter type.", 
									name, mono_class_get_namespace(pClass), mono_class_get_name(pClass), i + 1, mono_class_get_namespace(pItemClass), mono_class_get_name(pItemClass));
							}
							break;
						}
					}
				}

				if(i + 1 == suppliedArgsCount)
					return new CScriptMethod(pCurMethod);
			}
		}
	}

	if(throwOnFail)
	{
		if(IMonoException *pException = GetMonoScriptSystem()->GetCorlibAssembly()->GetException("System", "MissingMethodException", "Failed to locate method %s in class %s", name, GetName()))
			pException->Throw();
	}

	return nullptr;
}