Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Il2CppSystem.ValueType parameters with default value throw an exception when not provided. #136

Open
extraes opened this issue Jun 23, 2024 · 0 comments

Comments

@extraes
Copy link

extraes commented Jun 23, 2024

As an example and for ease of demonstration, unhollowed code from BONELAB is provided:

[CallerCount(14)]
[CachedScanResults(RefRangeStart = 929796, RefRangeEnd = 929810, XrefRangeStart = 929785, XrefRangeEnd = 929796, MetadataInitTokenRva = 0L, MetadataInitFlagRva = 0L)]
public unsafe static UniTask Delay([DefaultParameterValue(null)] int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = null)
{
    System.IntPtr* ptr = stackalloc System.IntPtr[4];
    *ptr = (nint)(&millisecondsDelay);
    *(bool**)((byte*)ptr + checked((nuint)1u * unchecked((nuint)sizeof(System.IntPtr)))) = &ignoreTimeScale;
    *(PlayerLoopTiming**)((byte*)ptr + checked((nuint)2u * unchecked((nuint)sizeof(System.IntPtr)))) = &delayTiming;
    *(System.IntPtr*)((byte*)ptr + checked((nuint)3u * unchecked((nuint)sizeof(System.IntPtr)))) = IL2CPP.il2cpp_object_unbox(IL2CPP.Il2CppObjectBaseToPtrNotNull(cancellationToken));
    System.Runtime.CompilerServices.Unsafe.SkipInit(out System.IntPtr exc);
    System.IntPtr pointer = IL2CPP.il2cpp_runtime_invoke(NativeMethodInfoPtr_Delay_Public_Static_UniTask_Int32_Boolean_PlayerLoopTiming_CancellationToken_0, (System.IntPtr)0, (void**)ptr, ref exc);
    Il2CppException.RaiseExceptionIfNecessary(exc);
    return new UniTask(pointer);
}

The relevant portions are the following:

  • The parameter CancellationToken cancellationToken = null
  • The conversion/packing of this parameter IL2CPP.il2cpp_object_unbox(IL2CPP.Il2CppObjectBaseToPtrNotNull(cancellationToken))

The parameter is of class type CancellationToken, extending Il2CppSystem.ValueType (unhollowed version of the struct CancellationToken)
In the source code for this method in the UniTask repository, this parameter is normally defined as CancellationToken cancellationToken = default(CancellationToken)
The unhollowed parameter being defined as null causes a problem when this method is called without filling out all parameters, because obviously Il2CppObjectBaseToPtrNotNull throws an exception when it is null.

This can be remedied on a per-method basis by prefixing the offending methods and replacing parameters, but this is manual and still represents a bug in the generated IL. A solution could be making the IL mirror IL2CPP.Il2CppObjectBaseToPtrNotNull(cancellationToken ?? new CancellationToken()), or keep a cached copy of a default CancellationToken and retrieving that field, to avoid recreating objects, but there's more complexity to keeping that field and possibly making sure it's not collected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant