@@ -1438,5 +1438,93 @@ public Native(S s)
14381438
14391439 public static string TypeUsage ( string attr ) => MarshalUsingParametersAndModifiers ( "S" , "Marshaller" , attr ) ;
14401440 }
1441+
1442+ public const string ImproperCollectionWithMarshalUsingOnElements = """
1443+ using System;
1444+ using System.Collections.Generic;
1445+ using System.Runtime.InteropServices;
1446+ using System.Runtime.InteropServices.Marshalling;
1447+
1448+ class MyList<T>
1449+ {
1450+ }
1451+
1452+ class NotMyList {}
1453+
1454+ class Example
1455+ {
1456+ public int Value;
1457+ }
1458+
1459+ internal static partial class PInvoke
1460+ {
1461+ [LibraryImport("NativeLibrary", EntryPoint = "ProcessExample")]
1462+ public static partial int ProcessExample([MarshalUsing(typeof(ListMarshaller<,>), CountElementName = nameof(exampleCount)), MarshalUsing(typeof(ExampleMarshaller), ElementIndirectionDepth = 1)] MyList<Example> examples, ref int exampleCount);
1463+ }
1464+
1465+ [ContiguousCollectionMarshaller]
1466+ [CustomMarshaller(typeof(MyList<>), MarshalMode.Default, typeof(ListMarshaller<,>.Marshaller))]
1467+ public unsafe static class ListMarshaller<T, TUnmanagedElement> where TUnmanagedElement : unmanaged
1468+ {
1469+ public static class Marshaller
1470+ {
1471+ public static byte* AllocateContainerForUnmanagedElements(NotMyList managed, out int numElements)
1472+ {
1473+ numElements = default;
1474+ return default;
1475+ }
1476+
1477+ public static ReadOnlySpan<T> GetManagedValuesSource(NotMyList managed)
1478+ => default;
1479+
1480+ public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(byte* unmanaged, int numElements)
1481+ => new Span<TUnmanagedElement>((TUnmanagedElement*)unmanaged, numElements);
1482+
1483+ public static List<T> AllocateContainerForManagedElements(byte* unmanaged, int length)
1484+ => new List<T>(length);
1485+
1486+ public static Span<T> GetManagedValuesDestination(NotMyList managed)
1487+ => default;
1488+
1489+ public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(byte* nativeValue, int numElements)
1490+ => new ReadOnlySpan<TUnmanagedElement>((TUnmanagedElement*)nativeValue, numElements);
1491+
1492+ public static void Free(byte* unmanaged)
1493+ => NativeMemory.Free(unmanaged);
1494+ }
1495+ }
1496+
1497+ [CustomMarshaller(typeof(Example), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
1498+ [CustomMarshaller(typeof(Example), MarshalMode.ManagedToUnmanagedOut, typeof(ManagedToNativeOutFinally))]
1499+ static class ExampleMarshaller
1500+ {
1501+ public static class ManagedToNativeOutFinally
1502+ {
1503+ public static Example ConvertToManagedFinally(int managed)
1504+ {
1505+ return default;
1506+ }
1507+
1508+ public static void Free(int unmanaged)
1509+ {
1510+ }
1511+ }
1512+
1513+ public struct ManagedToNative
1514+ {
1515+ Example managed;
1516+
1517+ public static int BufferSize => sizeof(int);
1518+
1519+ public void FromManaged(Example managed, Span<int> buffer) => this.managed = managed;
1520+
1521+ public int ToUnmanaged() => managed.Value;
1522+
1523+ public void OnInvoked() { }
1524+
1525+ public void Free() { }
1526+ }
1527+ }
1528+ """ ;
14411529 }
14421530}
0 commit comments