Skip to content

Commit f39ea5a

Browse files
authored
Fix "Handle is not initialized" for Unity 2021.2.x games (#232)
When the mono object is a System.Action object it seems GetGcHandlePtrFromIl2CppObject(pointer) returns a null pointer for the Garbage Collector Handle (or well IntPtr.Zero). This causes GCHandle.FromIntPtr(gcHandle) to throw an excepction. One solution after a lot of back and forth was to essentially check if the object class is a Delegate type class (which includes System.Action) and if so, get the garbage collector handle on the mTarget of the delegate object. This way in my testing the code will not interfere with other Unity versions - yet it allows to hook onto my test game - which happens to be a 2021.2.x game compiled with IL2CPP. In other Unity versions if (gcHandle == IntPtr.Zero) should be false so I doubt this would interfere in any way (it worked fine in other tested games for me). ---- It's a hack but it seems to be working well, merging for v1.5.1. This code will be replaced in v2.0 with a proper fix.
1 parent 400ad63 commit f39ea5a

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

Il2CppInterop.Runtime/Runtime/ClassInjectorBase.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,30 @@ public static class ClassInjectorBase
1313
public static object GetMonoObjectFromIl2CppPointer(IntPtr pointer)
1414
{
1515
var gcHandle = GetGcHandlePtrFromIl2CppObject(pointer);
16+
17+
if (gcHandle == IntPtr.Zero) // The Garbage collector handle might return a null pointer
18+
{
19+
gcHandle = FallbackGetGcHandlePtrFromIl2CppDelegateMTarget(pointer);
20+
}
21+
1622
return GCHandle.FromIntPtr(gcHandle).Target;
1723
}
1824

25+
/// <summary>
26+
/// Tries to get the Garbage collector pointer from the m_target object from the m_target of the delegate.
27+
/// Fixes Harmony in Unity 2021.2.x .
28+
/// </summary>
29+
private static IntPtr FallbackGetGcHandlePtrFromIl2CppDelegateMTarget(IntPtr pointer)
30+
{
31+
if (IL2CPP.il2cpp_class_is_assignable_from(Il2CppClassPointerStore<Il2CppSystem.MulticastDelegate>.NativeClassPtr, IL2CPP.il2cpp_object_get_class(pointer)))
32+
{
33+
var delegateObject = new Il2CppSystem.Delegate(pointer);
34+
if (delegateObject.m_target != null && delegateObject.m_target.Pointer != IntPtr.Zero)
35+
return GetGcHandlePtrFromIl2CppObject(delegateObject.m_target.Pointer);
36+
}
37+
return IntPtr.Zero;
38+
}
39+
1940
public static unsafe IntPtr GetGcHandlePtrFromIl2CppObject(IntPtr pointer)
2041
{
2142
return GetInjectedData(pointer)->managedGcHandle;

0 commit comments

Comments
 (0)