Вызвать универсальный метод через отражение в C # IL2CPP на iOS - PullRequest
0 голосов
/ 17 мая 2019

Этот вопрос конкретно касается 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 Ответ

3 голосов
/ 17 мая 2019

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

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

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

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

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

...