microsoft / CsWin32

A source generator to add a user-defined set of Win32 P/Invoke methods and supporting types to a C# project.
MIT License
1.99k stars 84 forks source link

NetFramework - Unsafe.SkipInit(out T value) unavailable #1206

Closed RFBomb closed 3 weeks ago

RFBomb commented 3 weeks ago

Actual behavior

Windows.Wdk.byte.InlineArrays.g.cs and Windows.Wdk.char.InlineArrays.g.cs both cause project to not build due to image

Relevant section of CSWin32 : https://github.com/microsoft/CsWin32/blob/66fe74557fb1412085f01be9cd27c20e7af97de8/src/Microsoft.Windows.CsWin32/Generator.InlineArrays.cs#L608

Note : This ONLY occurs if using the System.Memory Nuget package!

Generated Code: (with System.Memory)

public static unsafe implicit operator __byte_1(ReadOnlySpan<byte> value)
{
    Unsafe.SkipInit(out __byte_1 result);
    Span<byte> target = new Span<byte>(result.Value, SpanLength);
    value.CopyTo(target);
    int initLength = value.Length;
    target.Slice(initLength, SpanLength - initLength).Clear();
    return result;
}

Generated code without System.Memory ( Note how the error occurs, even though the line doesn't exist! ) image

Expected behavior

Generate code compatible with the target ( in this case Net462 and Net48 )

Repro steps

  1. NativeMethods.txt content: REPARSE_DATA_BUFFER

  2. Multitarget Net462 or Net48 along with your .Net of choice

  3. NativeMethods.json content (if present): not applicable

  4. Any of your own code that should be shared?

Context

riQQ commented 3 weeks ago

See also #1199

RFBomb commented 3 weeks ago

@riQQ - glad I'm not the only one. The repo I'm working on has a super-basic console app, so I tested that real quick as a minimal-reproduceable project, and it was not able to be reproduced!!

This seems to be resolved by nuget package 0.3.106, which generates Windows.Win32.VariableLengthInlineArray<T> instead

Closing this as A) it appears to be a duplicate, and B) updating the nuget pkg for this library resolved the issue.

Thanks for the quick response!

RFBomb commented 3 weeks ago

Just for reference here, here is the generated code:

Net462

    internal struct VariableLengthInlineArray<T>
where T : unmanaged
    {
        internal T e0;

        [UnscopedRef]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal Span<T> AsSpan(int length)

        {
unsafe

            {
                fixed (void* p = &this.e0)
                {
                    return new Span<T>(p, length);
                }
            }
        }
    }

Net8.0

    internal struct VariableLengthInlineArray<T>
where T : unmanaged
    {
        internal T e0;

        internal ref T this[int index]
        {
                        [UnscopedRef]
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref Unsafe.Add(ref this.e0, index);
        }

        [UnscopedRef]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal Span<T> AsSpan(int length)

        {
            return MemoryMarshal.CreateSpan(ref this.e0, length);
        }
    }