beatsaber-hook icon indicating copy to clipboard operation
beatsaber-hook copied to clipboard

MakeGenericMethod

Open OliverXH opened this issue 1 year ago • 2 comments

Unity Version: 2021.3.16f1 (4016570cf34f)

In this version 2021.3.16f1, struct Il2CppDefaults dosen't have mono_method_class property, so I can't get mono_method_class in file typedefs.h here is the relevant code:

DEFINE_IL2CPP_DEFAULT_TYPE(Il2CppReflectionMethod*, mono_method);

In il2cpp_utils::MakeGenericMethod() method, it calls the MakeGenericMethod method in Il2CppClass mono_method_calss:

auto res = il2cpp_utils::RunMethod<Il2CppReflectionMethod*, false>(infoObj, "MakeGenericMethod", arr);

So, how should I make a method from generic method in this version?

// C#

// Invoke the method get from generic method
System.Reflection.MethodInfo mi = typeof(Component).GetMethod("GetComponent", System.Type.EmptyTypes);
System.Reflection.MethodInfo miConstructed = mi.MakeGenericMethod(typeof(Rigidbody));
Rigidbody rigidbody = (Rigidbody)miConstructed.Invoke(this, null);

// Invoke the method normally.
Rigidbody rigidbody = GetComponent<Rigidbody>();

OliverXH avatar May 13 '23 03:05 OliverXH

Apologies for only catching up to this now (literally 5 months after you posted this...) Unity 2021 is not yet supported. As for making generic methods, I'd need to do a bit of looking to see how they get forwarded on latest, but the current approach is already a hack over a hack-- we could stand to replace it with more correct behavior, where we inflate the metadata directly to make a MethodInfo* that we can use for invokes.

Really, we don't even need a MethodInfo*, we could just use the AOT generated method pointers directly. I'll leave this open for now and when unity 2021 support lands, I'll update this.

sc2ad avatar Oct 15 '23 07:10 sc2ad

Based on your code, with some modifications, it is now functioning correctly.

I examined the code in the il2cpp-object-internals.h file in the libil2cpp folder of Unity. There is a definition for Il2CppReflectionMethod:

// System.Reflection.MonoMethod
typedef struct Il2CppReflectionMethod
{
    Il2CppObject object;
    const MethodInfo *method;
    Il2CppString *name;
    Il2CppReflectionType *reftype;
} Il2CppReflectionMethod;

In C#, System.Reflection.MonoMethod inherits from RuntimeMethodInfo. I found the definition of the MakeGenericMethod method in RuntimeMethodInfo here.

Therefore, I replaced mono_method_class with System.Reflection.RuntimeMethodInfo:

Il2CppClass *method_class = il2cpp_class_from_name(il2cpp_defaults.corlib, "System.Reflection", "RuntimeMethodInfo");
const MethodInfo *method_MakeGenericMethod = il2cpp_class_get_method_from_name(method_class, "MakeGenericMethod", 1);

That's all.

OliverXH avatar Oct 16 '23 01:10 OliverXH