Вызвать универсальный метод через отражение в C # IL2CPP на iOS

Этот вопрос конкретно о Unity3d IL2CPP и iOS.

Вызов универсального метода с использованием отражения

class SourceValue<T> { public T value; }
class TargetValue<T> { public T value; }

static TargetValue<T> GenericMethod<T> (SourceValue<T> source) {
    return new TargetValue<T> { value = source.value };
}

void Main () {
    Type genericType = typeof(SourceValue<float>);
    Type typeArg = genericType.GenericTypeArguments[0];
    MethodInfo mi = GetType ().GetMethod ("GenericMethod", Flags | BindingFlags.Static);
    MethodInfo gmi = mi.MakeGenericMethod (typeArg);
    object src = new SourceValue<float> { value = 0.5f };
    object trg = gmi.Invoke (this, new object[] { src });
}

Это работает, как и ожидалось, при запуске в редакторе Unity на Mac. Вызывает сбой на iOS с ошибкой:

ExecutionEngineException: Attempting to call method 'GenericMethod<System.Single>' for which no ahead of time (AOT) code was generated.
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0  

Просто система AOT не может вызывать универсальные методы или я что-то упустил?

Всего 1 ответ


Да, поскольку IL2CPP является компилятором с опережением времени (AOT), он работает только для кода, который существует во время компиляции. Никакой код здесь не использует GenericMethod<float> в «реальном» исходном коде C #, поэтому IL2CPP не знает, как сгенерировать соответствующий код, чтобы эта реализация работала.

Реальное ограничение здесь заключается в том, что универсальным типом аргумента является float , который является типом значения. Вы можете использовать string (ссылочный тип) в этом случае без каких-либо проблем. IL2CPP разделяет реализацию всех универсальных типов, которые имеют универсальный аргумент, который является ссылочным типом (например, string , object и т. Д.). Это возможно, потому что все ссылочные типы в C # имеют одинаковый размер ( IntrPtr.Size , IntrPtr.Size ).

Таким образом, ограничение здесь действительно двоякое:

  1. IL2CPP может генерировать только код, о котором известно во время компиляции
  2. Это ограничение применяется только к универсальным типам, когда аргумент типа является типом значения.

Обратите внимание, что теоретически IL2CPP также может совместно использовать реализацию универсальных типов с универсальными аргументами типа значения, хотя это еще не было реализовано.


Есть идеи?

10000