Il2CppInterop icon indicating copy to clipboard operation
Il2CppInterop copied to clipboard

Injected fields returning injected types cause a crash

Open simonkellly opened this issue 1 year ago • 3 comments

If you do the following

[BepInAutoPlugin]
public partial class TestPluginPlugin : BasePlugin
{
    public override void Load()
    {
        ClassInjector.RegisterTypeInIl2Cpp<MyBehaviour>();
        ClassInjector.RegisterTypeInIl2Cpp<MyTestObj>();
        
        MyBehaviour myBehaviour = new GameObject().AddComponent(Il2CppType.Of<MyBehaviour>()).Cast<MyBehaviour>();
        MyTestObj myTestObj = new GameObject().AddComponent(Il2CppType.Of<MyTestObj>()).Cast<MyTestObj>();
        myTestObj.myBehaviour.Value = myBehaviour;

        MyTestObj myNewTest = Object.Instantiate(myTestObj).Cast<MyTestObj>();
        Log.LogMessage("myNewTest.myBehaviour.mySpriteRenderer: " + myNewTest.myBehaviour.Value);
    }
}

public class MyBehaviour : MonoBehaviour
{
    public MyBehaviour(IntPtr ptr) : base(ptr) { }
    
    public Il2CppReferenceField<GameObject> mySpriteRenderer;
}

public class MyTestObj : MonoBehaviour
{
    public MyTestObj(IntPtr ptr) : base(ptr) { }

    public Il2CppReferenceField<MyBehaviour > myBehaviour;
}

The game will crash once you call Object.Instantiate(myTestObj)

Though, if you switch the return type to be something more generic i.e MonoBehaviour in myBehaviour, it works fine

simonkellly avatar Jun 17 '23 01:06 simonkellly

💤

Alexejhero avatar Oct 24 '23 18:10 Alexejhero

image

Alexejhero avatar Jun 18 '24 23:06 Alexejhero

Decompiling that method (for my game) in ILSpy, I get some warnings, which may or may not be related.

public unsafe static T Instantiate<T>(T original) where T : Object
{
	//IL_0051->IL0056: Incompatible stack types: I vs Ref
	//IL_0044->IL0056: Incompatible stack types: I vs Ref
	IntPtr* ptr = stackalloc IntPtr[1];
	ref T reference;
	if (!typeof(T).IsValueType)
	{
		T val = original;
		reference = ref *(?*)((!(val is string)) ? IL2CPP.Il2CppObjectBaseToPtr(val as Il2CppObjectBase) : IL2CPP.ManagedStringToIl2Cpp(val as string));
	}
	else
	{
		reference = ref original;
	}
	*ptr = (nint)System.Runtime.CompilerServices.Unsafe.AsPointer(ref reference);
	System.Runtime.CompilerServices.Unsafe.SkipInit(out IntPtr exc);
	IntPtr objectPointer = IL2CPP.il2cpp_runtime_invoke(MethodInfoStoreGeneric_Instantiate_Public_Static_T_T_0<T>.Pointer, (IntPtr)0, (void**)ptr, ref exc);
	Il2CppException.RaiseExceptionIfNecessary(exc);
	return IL2CPP.PointerToValueGeneric<T>(objectPointer, isFieldPointer: false, valueTypeWouldBeBoxed: true);
}

ds5678 avatar Jul 15 '24 02:07 ds5678