diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs index d457e37a7f2b2..55818927c3965 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs @@ -630,8 +630,7 @@ private static bool UsesLastIndexMarshalled(TypePositionInfo info, StubCodeConte { return false; } - bool usesLastIndexMarshalled = !shouldCleanupAllElements && !onlyUnmarshals; - return usesLastIndexMarshalled; + return true; } private static bool ShouldCleanUpAllElements(TypePositionInfo info, StubCodeContext context) @@ -640,7 +639,7 @@ private static bool ShouldCleanUpAllElements(TypePositionInfo info, StubCodeCont _ = context; // AdditionalTemporaryStateLivesAcrossStages implies that it is an outer collection // Out parameters means that the contents are created by the P/Invoke and assumed to have successfully created all elements - return !context.AdditionalTemporaryStateLivesAcrossStages || info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out || info.RefKind == RefKind.Out; + return !context.AdditionalTemporaryStateLivesAcrossStages || info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out || info.RefKind == RefKind.Out || info.IsNativeReturnPosition; } public override StatementSyntax GenerateSetupStatement(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs index b6ed3dee43d54..37fce2297a88c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs @@ -56,33 +56,79 @@ internal struct StatefulFinallyNative public int i; } - [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.Default, typeof(StatefulFinallyTypeMarshaller))] + [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.ManagedToUnmanagedOut, typeof(UnmanagedToManaged))] + [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.UnmanagedToManagedIn, typeof(UnmanagedToManaged))] + [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))] + [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))] internal struct StatefulFinallyTypeMarshaller { - int managed_i; - int unmanaged_i; - public void FromManaged(StatefulFinallyType managed) + internal struct Bidirectional { - managed_i = managed.i; - } + int managed_i; + int unmanaged_i; - public StatefulFinallyNative ToUnmanaged() - { - return new StatefulFinallyNative() { i = this.managed_i }; - } + public void FromManaged(StatefulFinallyType managed) + { + managed_i = managed.i; + } - public void FromUnmanaged(StatefulFinallyNative unmanaged) - { - unmanaged_i = unmanaged.i; + public StatefulFinallyNative ToUnmanaged() + { + return new StatefulFinallyNative() { i = this.managed_i }; + } + + public void FromUnmanaged(StatefulFinallyNative unmanaged) + { + unmanaged_i = unmanaged.i; + } + + public StatefulFinallyType ToManagedFinally() + { + return new StatefulFinallyType() { i = unmanaged_i }; + } + + public void Free() { } + + public void OnInvoked() { } } - public StatefulFinallyType ToManagedFinally() + internal struct ManagedToUnmanaged { - return new StatefulFinallyType() { i = unmanaged_i }; + int managed_i; + + public void FromManaged(StatefulFinallyType managed) + { + managed_i = managed.i; + } + + public StatefulFinallyNative ToUnmanaged() + { + return new StatefulFinallyNative() { i = this.managed_i }; + } + + public void Free() { } + + public void OnInvoked() { } } - public void Free() + internal struct UnmanagedToManaged { + int unmanaged_i; + + public void FromUnmanaged(StatefulFinallyNative unmanaged) + { + unmanaged_i = unmanaged.i; + } + public StatefulFinallyType ToManagedFinally() + { + return new StatefulFinallyType() { i = unmanaged_i }; + } + + public void Free() { } + + public void OnInvoked() { } } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs index f84da40e9e2e0..a1df4de144823 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs @@ -24,34 +24,82 @@ internal class StatefulType { } - [CustomMarshaller(typeof(StatefulType), MarshalMode.Default, typeof(StatefulTypeMarshaller))] + [CustomMarshaller(typeof(StatefulType), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatefulType), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatefulType), MarshalMode.ManagedToUnmanagedOut, typeof(UnmanagedToManaged))] + [CustomMarshaller(typeof(StatefulType), MarshalMode.UnmanagedToManagedIn, typeof(UnmanagedToManaged))] + [CustomMarshaller(typeof(StatefulType), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))] + [CustomMarshaller(typeof(StatefulType), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))] internal struct StatefulTypeMarshaller { - public void FromManaged(StatefulType managed) + internal struct Bidirectional { - throw new System.NotImplementedException(); - } + public void FromManaged(StatefulType managed) + { + throw new System.NotImplementedException(); + } - public nint ToUnmanaged() - { - throw new System.NotImplementedException(); - } + public nint ToUnmanaged() + { + throw new System.NotImplementedException(); + } - public void FromUnmanaged(nint unmanaged) - { - throw new System.NotImplementedException(); + public void FromUnmanaged(nint unmanaged) + { + throw new System.NotImplementedException(); + } + + public StatefulType ToManaged() + { + throw new System.NotImplementedException(); + } + + public void Free() + { + throw new System.NotImplementedException(); + } + + public void OnInvoked() { } } - public StatefulType ToManaged() + internal struct ManagedToUnmanaged { - throw new System.NotImplementedException(); + public void FromManaged(StatefulType managed) + { + throw new System.NotImplementedException(); + } + + public nint ToUnmanaged() + { + throw new System.NotImplementedException(); + } + + public void Free() + { + throw new System.NotImplementedException(); + } + + public void OnInvoked() { } } - public void Free() + internal struct UnmanagedToManaged { - throw new System.NotImplementedException(); - } + public void FromUnmanaged(nint unmanaged) + { + throw new System.NotImplementedException(); + } - public void OnInvoked() { } + public StatefulType ToManaged() + { + throw new System.NotImplementedException(); + } + + public void Free() + { + throw new System.NotImplementedException(); + } + + public void OnInvoked() { } + } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs index ca6770fdf0440..0465f391e3b42 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs @@ -1,13 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; namespace SharedTypes.ComInterfaces { [GeneratedComInterface(), Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")] - partial interface IStatelessCollectionStatelessElement + internal partial interface IStatelessCollectionStatelessElement { void Method( [MarshalUsing(CountElementName = nameof(size))] StatelessCollection p, @@ -38,43 +39,103 @@ internal class StatelessCollection { } + internal struct NativeCollection + { + + } + [ContiguousCollectionMarshaller] - [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.Default, typeof(StatelessCollectionMarshaller<,>.Default))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(StatelessCollectionMarshaller<,>.ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.UnmanagedToManagedOut, typeof(StatelessCollectionMarshaller<,>.ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.ElementIn, typeof(StatelessCollectionMarshaller<,>.ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(StatelessCollectionMarshaller<,>.UnmanagedToManaged))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.UnmanagedToManagedIn, typeof(StatelessCollectionMarshaller<,>.UnmanagedToManaged))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.ElementOut, typeof(StatelessCollectionMarshaller<,>.UnmanagedToManaged))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.UnmanagedToManagedRef, typeof(StatelessCollectionMarshaller<,>.Bidirectional))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.ManagedToUnmanagedRef, typeof(StatelessCollectionMarshaller<,>.Bidirectional))] + [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.ElementRef, typeof(StatelessCollectionMarshaller<,>.Bidirectional))] internal static unsafe class StatelessCollectionMarshaller where TUnmanagedElement : unmanaged { - internal static class Default + internal static class Bidirectional + { + public static NativeCollection AllocateContainerForUnmanagedElements(StatelessCollection managed, out int numElements) + { + throw new NotImplementedException(); + } + + public static StatelessCollection AllocateContainerForManagedElements(NativeCollection unmanaged, int numElements) + { + throw new NotImplementedException(); + } + + public static ReadOnlySpan GetManagedValuesSource(StatelessCollection managed) + { + throw new NotImplementedException(); + } + + public static Span GetUnmanagedValuesDestination(NativeCollection unmanaged, int numElements) + { + throw new NotImplementedException(); + } + + public static ReadOnlySpan GetUnmanagedValuesSource(NativeCollection unmanaged, int numElements) + { + throw new NotImplementedException(); + } + + public static Span GetManagedValuesDestination(StatelessCollection managed) + { + throw new NotImplementedException(); + } + + public static void Free(NativeCollection unmanaged) { } + } + + internal static class ManagedToUnmanaged { - public static nint AllocateContainerForUnmanagedElements(StatelessCollection managed, out int numElements) + public static NativeCollection AllocateContainerForUnmanagedElements(StatelessCollection managed, out int numElements) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } - public static StatelessCollection AllocateContainerForManagedElements(nint unmanaged, int numElements) + public static ReadOnlySpan GetManagedValuesSource(StatelessCollection managed) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } - public static System.ReadOnlySpan GetManagedValuesSource(StatelessCollection managed) + public static Span GetUnmanagedValuesDestination(NativeCollection unmanaged, int numElements) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } - public static System.Span GetUnmanagedValuesDestination(nint unmanaged, int numElements) + public static void Free(NativeCollection unmanaged) => throw new NotImplementedException(); + + } + + internal static class UnmanagedToManaged + { + public static StatelessCollection AllocateContainerForManagedElements(NativeCollection unmanaged, int numElements) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } - public static System.ReadOnlySpan GetUnmanagedValuesSource(nint unmanaged, int numElements) + public static ReadOnlySpan GetUnmanagedValuesSource(NativeCollection unmanaged, int numElements) + { + throw new NotImplementedException(); + } + // Should be removed: https://github.com/dotnet/runtime/issues/89885 + public static Span GetUnmanagedValuesDestination(NativeCollection unmanaged, int numElements) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } - public static System.Span GetManagedValuesDestination(StatelessCollection managed) + public static Span GetManagedValuesDestination(StatelessCollection managed) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } - public static void Free(nint unmanaged) { } + public static void Free(NativeCollection unmanaged) => throw new NotImplementedException(); + } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs index c2c8d45e31ad5..325064ad8cbf9 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs @@ -23,10 +23,10 @@ internal partial interface IStatelessMarshalling [GeneratedComClass] internal partial class StatelessMarshalling : IStatelessMarshalling { - public void Method([MarshalUsing(CountElementName = "size")] StatelessType param, int size) { } - public void MethodIn([MarshalUsing(CountElementName = "size")] in StatelessType param, int size) { } - public void MethodOut([MarshalUsing(CountElementName = "size")] out StatelessType param, int size) { param = new StatelessType { I = 42 }; } - public void MethodRef([MarshalUsing(CountElementName = "size")] ref StatelessType param, int size) { param = new StatelessType { I = 200 }; } + public void Method(StatelessType param, int size) { } + public void MethodIn(in StatelessType param, int size) { } + public void MethodOut(out StatelessType param, int size) { param = new StatelessType { I = 42 }; } + public void MethodRef(ref StatelessType param, int size) { param = new StatelessType { I = 200 }; } public StatelessType Return() => throw new NotImplementedException(); public StatelessType ReturnPreserveSig() => throw new NotImplementedException(); } @@ -37,14 +37,39 @@ internal class StatelessType public int I; } - [CustomMarshaller(typeof(StatelessType), MarshalMode.Default, typeof(StatelessTypeMarshaller))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.ElementIn, typeof(ManagedToUnmanaged))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.ManagedToUnmanagedOut, typeof(UnmanagedToManaged))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.UnmanagedToManagedIn, typeof(UnmanagedToManaged))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.ElementOut, typeof(UnmanagedToManaged))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))] + [CustomMarshaller(typeof(StatelessType), MarshalMode.ElementRef, typeof(Bidirectional))] internal static class StatelessTypeMarshaller { - public static int FreeCount { get; private set; } - public static nint ConvertToUnmanaged(StatelessType managed) => managed.I; + internal static class Bidirectional + { + public static int FreeCount { get; private set; } + public static nint ConvertToUnmanaged(StatelessType managed) => managed.I; - public static StatelessType ConvertToManaged(nint unmanaged) => new StatelessType { I = (int)unmanaged }; + public static StatelessType ConvertToManaged(nint unmanaged) => new StatelessType { I = (int)unmanaged }; - public static void Free(nint unmanaged) => FreeCount++; + public static void Free(nint unmanaged) => FreeCount++; + } + + internal static class ManagedToUnmanaged + { + public static int FreeCount { get; private set; } + public static void Free(nint unmanaged) => FreeCount++; + public static nint ConvertToUnmanaged(StatelessType managed) => managed.I; + } + + internal static class UnmanagedToManaged + { + public static int FreeCount { get; private set; } + public static void Free(nint unmanaged) => FreeCount++; + public static StatelessType ConvertToManaged(nint unmanaged) => new StatelessType { I = (int)unmanaged }; + } } }