Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eng/generators.targets10
-rw-r--r--src/libraries/Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs168
-rw-r--r--src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems2
-rw-r--r--src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayMarshaller.cs166
-rw-r--r--src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/PointerArrayMarshaller.cs174
-rw-r--r--src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs9
-rw-r--r--src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs4
-rw-r--r--src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs4
-rw-r--r--src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs48
-rw-r--r--src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj3
10 files changed, 391 insertions, 197 deletions
diff --git a/eng/generators.targets b/eng/generators.targets
index 5d806b69a18..f830dbd52f2 100644
--- a/eng/generators.targets
+++ b/eng/generators.targets
@@ -50,16 +50,6 @@
Include="$(CoreLibSharedDir)System\Runtime\InteropServices\LibraryImportAttribute.cs" />
<Compile Condition="'$(NetCoreAppCurrentTargetFrameworkMoniker)' != '$(TargetFrameworkMoniker)'"
Include="$(CoreLibSharedDir)System\Runtime\InteropServices\StringMarshalling.cs" />
-
- <!-- Only add the following files if we are on the latest TFM (that is, net7) and the project is SPCL or has references to System.Runtime.CompilerServices.Unsafe and System.Memory -->
- <Compile Condition="'$(NetCoreAppCurrentTargetFrameworkMoniker)' == '$(TargetFrameworkMoniker)'
- and (
- '$(MSBuildProjectName)' == 'System.Private.CoreLib'
- or '$(EnableLibraryImportGenerator)' == 'true'
- or ('@(Reference)' != ''
- and @(Reference->AnyHaveMetadataValue('Identity', 'System.Memory')))
- or ('@(ProjectReference)' != ''
- and @(ProjectReference->AnyHaveMetadataValue('Identity', '$(CoreLibProject)'))))" Include="$(LibrariesProjectRoot)Common\src\System\Runtime\InteropServices\ArrayMarshaller.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs b/src/libraries/Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs
deleted file mode 100644
index f5c5277a7d3..00000000000
--- a/src/libraries/Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable enable
-
-//
-// Types in this file are used for generated p/invokes (docs/design/features/source-generator-pinvokes.md).
-//
-
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace System.Runtime.InteropServices.GeneratedMarshalling
-{
- // Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack.
- // Number kept small to ensure that P/Invokes with a lot of array parameters doesn't
- // blow the stack since this is a new optimization in the code-generated interop.
- [CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder[]), CustomTypeMarshallerKind.LinearCollection, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling, BufferSize = 0x200)]
-#if LIBRARYIMPORT_GENERATOR_TEST
- public
-#else
- internal
-#endif
- unsafe ref struct ArrayMarshaller<T>
- {
- private T[]? _managedArray;
- private readonly int _sizeOfNativeElement;
- private IntPtr _allocatedMemory;
-
- public ArrayMarshaller(int sizeOfNativeElement)
- : this()
- {
- _sizeOfNativeElement = sizeOfNativeElement;
- }
-
- public ArrayMarshaller(T[]? managed, int sizeOfNativeElement)
- :this(managed, Span<byte>.Empty, sizeOfNativeElement)
- {
- }
-
- public ArrayMarshaller(T[]? managed, Span<byte> stackSpace, int sizeOfNativeElement)
- {
- _allocatedMemory = default;
- _sizeOfNativeElement = sizeOfNativeElement;
- if (managed is null)
- {
- _managedArray = null;
- NativeValueStorage = default;
- return;
- }
- _managedArray = managed;
- // Always allocate at least one byte when the array is zero-length.
- int spaceToAllocate = Math.Max(managed.Length * _sizeOfNativeElement, 1);
- if (spaceToAllocate <= stackSpace.Length)
- {
- NativeValueStorage = stackSpace[0..spaceToAllocate];
- }
- else
- {
- _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
- NativeValueStorage = new Span<byte>((void*)_allocatedMemory, spaceToAllocate);
- }
- }
-
- public ReadOnlySpan<T> GetManagedValuesSource() => _managedArray;
- public Span<T> GetManagedValuesDestination(int length) => _allocatedMemory == IntPtr.Zero ? null : _managedArray = new T[length];
- public Span<byte> GetNativeValuesDestination() => NativeValueStorage;
-
- public ReadOnlySpan<byte> GetNativeValuesSource(int length)
- {
- return _allocatedMemory == IntPtr.Zero ? default : NativeValueStorage = new Span<byte>((void*)_allocatedMemory, length * _sizeOfNativeElement);
- }
- private Span<byte> NativeValueStorage { get; set; }
-
- public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(NativeValueStorage);
-
-
- public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
-
- public void FromNativeValue(byte* value)
- {
- _allocatedMemory = (IntPtr)value;
- }
-
- public T[]? ToManaged() => _managedArray;
-
- public void FreeNative()
- {
- Marshal.FreeCoTaskMem(_allocatedMemory);
- }
- }
-
- // Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack.
- // Number kept small to ensure that P/Invokes with a lot of array parameters doesn't
- // blow the stack since this is a new optimization in the code-generated interop.
- [CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder*[]), CustomTypeMarshallerKind.LinearCollection, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling, BufferSize = 0x200)]
-#if LIBRARYIMPORT_GENERATOR_TEST
- public
-#else
- internal
-#endif
- unsafe ref struct PtrArrayMarshaller<T> where T : unmanaged
- {
- private T*[]? _managedArray;
- private readonly int _sizeOfNativeElement;
- private IntPtr _allocatedMemory;
-
- public PtrArrayMarshaller(int sizeOfNativeElement)
- : this()
- {
- _sizeOfNativeElement = sizeOfNativeElement;
- }
-
- public PtrArrayMarshaller(T*[]? managed, int sizeOfNativeElement)
- :this(managed, Span<byte>.Empty, sizeOfNativeElement)
- {
- }
-
- public PtrArrayMarshaller(T*[]? managed, Span<byte> stackSpace, int sizeOfNativeElement)
- {
- _allocatedMemory = default;
- _sizeOfNativeElement = sizeOfNativeElement;
- if (managed is null)
- {
- _managedArray = null;
- NativeValueStorage = default;
- return;
- }
- _managedArray = managed;
- // Always allocate at least one byte when the array is zero-length.
- int spaceToAllocate = Math.Max(managed.Length * _sizeOfNativeElement, 1);
- if (spaceToAllocate <= stackSpace.Length)
- {
- NativeValueStorage = stackSpace[0..spaceToAllocate];
- }
- else
- {
- _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
- NativeValueStorage = new Span<byte>((void*)_allocatedMemory, spaceToAllocate);
- }
- }
-
- public ReadOnlySpan<IntPtr> GetManagedValuesSource() => Unsafe.As<IntPtr[]>(_managedArray);
- public Span<IntPtr> GetManagedValuesDestination(int length) => _allocatedMemory == IntPtr.Zero ? null : Unsafe.As<IntPtr[]>(_managedArray = new T*[length]);
- public Span<byte> GetNativeValuesDestination() => NativeValueStorage;
-
- public ReadOnlySpan<byte> GetNativeValuesSource(int length)
- {
- return _allocatedMemory == IntPtr.Zero ? default : NativeValueStorage = new Span<byte>((void*)_allocatedMemory, length * _sizeOfNativeElement);
- }
- private Span<byte> NativeValueStorage { get; set; }
-
- public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(NativeValueStorage);
- public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
-
- public void FromNativeValue(byte* value)
- {
- _allocatedMemory = (IntPtr)value;
- }
-
- public T*[]? ToManaged() => _managedArray;
-
- public void FreeNative()
- {
- Marshal.FreeCoTaskMem(_allocatedMemory);
- }
- }
-}
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index b76fee8bac7..985fcd2e870 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -789,6 +789,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\AllowReversePInvokeCallsAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\AnsiStringMarshaller.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Architecture.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\ArrayMarshaller.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\ArrayWithOffset.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\BestFitMappingAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\BStrWrapper.cs" />
@@ -872,6 +873,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OptionalAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OSPlatform.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OutAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\PointerArrayMarshaller.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\PosixSignal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\PosixSignalContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\PosixSignalRegistration.cs" />
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayMarshaller.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayMarshaller.cs
new file mode 100644
index 00000000000..4282b96f630
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayMarshaller.cs
@@ -0,0 +1,166 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// Marshaller for arrays
+ /// </summary>
+ /// <typeparam name="T">Array element type</typeparam>
+ [CLSCompliant(false)]
+ [CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder[]),
+ CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
+ Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
+ public unsafe ref struct ArrayMarshaller<T>
+ {
+ private readonly int _sizeOfNativeElement;
+
+ private T[]? _managedArray;
+ private IntPtr _allocatedMemory;
+ private Span<byte> _span;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ArrayMarshaller{T}"/>.
+ /// </summary>
+ /// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
+ public ArrayMarshaller(int sizeOfNativeElement)
+ : this()
+ {
+ _sizeOfNativeElement = sizeOfNativeElement;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ArrayMarshaller{T}"/>.
+ /// </summary>
+ /// <param name="array">Array to be marshalled.</param>
+ /// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
+ public ArrayMarshaller(T[]? array, int sizeOfNativeElement)
+ : this(array, Span<byte>.Empty, sizeOfNativeElement)
+ { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ArrayMarshaller{T}"/>.
+ /// </summary>
+ /// <param name="array">Array to be marshalled.</param>
+ /// <param name="buffer">Buffer that may be used for marshalling.</param>
+ /// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
+ /// <remarks>
+ /// The <paramref name="buffer"/> must not be movable - that is, it should not be
+ /// on the managed heap or it should be pinned.
+ /// <seealso cref="CustomTypeMarshallerFeatures.CallerAllocatedBuffer"/>
+ /// </remarks>
+ public ArrayMarshaller(T[]? array, Span<byte> buffer, int sizeOfNativeElement)
+ {
+ _allocatedMemory = default;
+ _sizeOfNativeElement = sizeOfNativeElement;
+ if (array is null)
+ {
+ _managedArray = null;
+ _span = default;
+ return;
+ }
+
+ _managedArray = array;
+
+ // Always allocate at least one byte when the array is zero-length.
+ int spaceToAllocate = Math.Max(array.Length * _sizeOfNativeElement, 1);
+ if (spaceToAllocate <= buffer.Length)
+ {
+ _span = buffer[0..spaceToAllocate];
+ }
+ else
+ {
+ _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
+ _span = new Span<byte>((void*)_allocatedMemory, spaceToAllocate);
+ }
+ }
+
+ /// <summary>
+ /// Gets a span that points to the memory where the managed values of the array are stored.
+ /// </summary>
+ /// <returns>Span over managed values of the array.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.In"/>
+ /// </remarks>
+ public ReadOnlySpan<T> GetManagedValuesSource() => _managedArray;
+
+ /// <summary>
+ /// Gets a span that points to the memory where the unmarshalled managed values of the array should be stored.
+ /// </summary>
+ /// <param name="length">Length of the array.</param>
+ /// <returns>Span where managed values of the array should be stored.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.Out"/>
+ /// </remarks>
+ public Span<T> GetManagedValuesDestination(int length) => _allocatedMemory == IntPtr.Zero ? null : _managedArray = new T[length];
+
+ /// <summary>
+ /// Returns a span that points to the memory where the native values of the array are stored after the native call.
+ /// </summary>
+ /// <param name="length">Length of the array.</param>
+ /// <returns>Span over the native values of the array.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.Out"/>
+ /// </remarks>
+ public ReadOnlySpan<byte> GetNativeValuesSource(int length)
+ {
+ return _allocatedMemory == IntPtr.Zero ? default : _span = new Span<byte>((void*)_allocatedMemory, length * _sizeOfNativeElement);
+ }
+
+ /// <summary>
+ /// Returns a span that points to the memory where the native values of the array should be stored.
+ /// </summary>
+ /// <returns>Span where native values of the array should be stored.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.In"/>
+ /// </remarks>
+ public Span<byte> GetNativeValuesDestination() => _span;
+
+ /// <summary>
+ /// Returns a reference to the marshalled array.
+ /// </summary>
+ public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
+
+ /// <summary>
+ /// Returns the native value representing the array.
+ /// </summary>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
+ /// </remarks>
+ public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
+
+ /// <summary>
+ /// Sets the native value representing the array.
+ /// </summary>
+ /// <param name="value">The native value.</param>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
+ /// </remarks>
+ public void FromNativeValue(byte* value)
+ {
+ _allocatedMemory = (IntPtr)value;
+ }
+
+ /// <summary>
+ /// Returns the managed array.
+ /// </summary>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.Out"/>
+ /// </remarks>
+ public T[]? ToManaged() => _managedArray;
+
+ /// <summary>
+ /// Frees native resources.
+ /// </summary>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerFeatures.UnmanagedResources"/>
+ /// </remarks>
+ public void FreeNative()
+ {
+ Marshal.FreeCoTaskMem(_allocatedMemory);
+ }
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/PointerArrayMarshaller.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/PointerArrayMarshaller.cs
new file mode 100644
index 00000000000..0d998b834a1
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/PointerArrayMarshaller.cs
@@ -0,0 +1,174 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// Marshaller for arrays of pointers
+ /// </summary>
+ /// <typeparam name="T">Array element pointer type</typeparam>
+ [CLSCompliant(false)]
+ [CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder*[]),
+ CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
+ Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
+ public unsafe ref struct PointerArrayMarshaller<T> where T : unmanaged
+ {
+ private readonly int _sizeOfNativeElement;
+
+ private T*[]? _managedArray;
+ private IntPtr _allocatedMemory;
+ private Span<byte> _span;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PointerArrayMarshaller{T}"/>.
+ /// </summary>
+ /// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
+ public PointerArrayMarshaller(int sizeOfNativeElement)
+ : this()
+ {
+ _sizeOfNativeElement = sizeOfNativeElement;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PointerArrayMarshaller{T}"/>.
+ /// </summary>
+ /// <param name="array">Array to be marshalled.</param>
+ /// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
+ public PointerArrayMarshaller(T*[]? array, int sizeOfNativeElement)
+ : this(array, Span<byte>.Empty, sizeOfNativeElement)
+ { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PointerArrayMarshaller{T}"/>.
+ /// </summary>
+ /// <param name="array">Array to be marshalled.</param>
+ /// <param name="buffer">Buffer that may be used for marshalling.</param>
+ /// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
+ /// <remarks>
+ /// The <paramref name="buffer"/> must not be movable - that is, it should not be
+ /// on the managed heap or it should be pinned.
+ /// <seealso cref="CustomTypeMarshallerFeatures.CallerAllocatedBuffer"/>
+ /// </remarks>
+ public PointerArrayMarshaller(T*[]? array, Span<byte> buffer, int sizeOfNativeElement)
+ {
+ _allocatedMemory = default;
+ _sizeOfNativeElement = sizeOfNativeElement;
+ if (array is null)
+ {
+ _managedArray = null;
+ _span = default;
+ return;
+ }
+
+ _managedArray = array;
+
+ // Always allocate at least one byte when the array is zero-length.
+ int spaceToAllocate = Math.Max(array.Length * _sizeOfNativeElement, 1);
+ if (spaceToAllocate <= buffer.Length)
+ {
+ _span = buffer[0..spaceToAllocate];
+ }
+ else
+ {
+ _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
+ _span = new Span<byte>((void*)_allocatedMemory, spaceToAllocate);
+ }
+ }
+
+ /// <summary>
+ /// Gets a span that points to the memory where the managed values of the array are stored.
+ /// </summary>
+ /// <returns>Span over managed values of the array.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.In"/>
+ /// </remarks>
+ public ReadOnlySpan<IntPtr> GetManagedValuesSource() => Unsafe.As<IntPtr[]>(_managedArray);
+
+ /// <summary>
+ /// Gets a span that points to the memory where the unmarshalled managed values of the array should be stored.
+ /// </summary>
+ /// <param name="length">Length of the array.</param>
+ /// <returns>Span where managed values of the array should be stored.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.Out"/>
+ /// </remarks>
+ public Span<IntPtr> GetManagedValuesDestination(int length)
+ {
+ if (_allocatedMemory == IntPtr.Zero)
+ return null;
+
+ _managedArray = new T*[length];
+ return Unsafe.As<IntPtr[]>(_managedArray);
+ }
+
+ /// <summary>
+ /// Returns a span that points to the memory where the native values of the array are stored after the native call.
+ /// </summary>
+ /// <param name="length">Length of the array.</param>
+ /// <returns>Span over the native values of the array.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.Out"/>
+ /// </remarks>
+ public ReadOnlySpan<byte> GetNativeValuesSource(int length)
+ {
+ if (_allocatedMemory == IntPtr.Zero)
+ return default;
+
+ _span = new Span<byte>((void*)_allocatedMemory, length * _sizeOfNativeElement);
+ return _span;
+ }
+
+ /// <summary>
+ /// Returns a span that points to the memory where the native values of the array should be stored.
+ /// </summary>
+ /// <returns>Span where native values of the array should be stored.</returns>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.In"/>
+ /// </remarks>
+ public Span<byte> GetNativeValuesDestination() => _span;
+
+ /// <summary>
+ /// Returns a reference to the marshalled array.
+ /// </summary>
+ public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
+
+ /// <summary>
+ /// Returns the native value representing the array.
+ /// </summary>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
+ /// </remarks>
+ public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
+
+ /// <summary>
+ /// Sets the native value representing the array.
+ /// </summary>
+ /// <param name="value">The native value.</param>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
+ /// </remarks>
+ public void FromNativeValue(byte* value) => _allocatedMemory = (IntPtr)value;
+
+ /// <summary>
+ /// Returns the managed array.
+ /// </summary>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerDirection.Out"/>
+ /// </remarks>
+ public T*[]? ToManaged() => _managedArray;
+
+ /// <summary>
+ /// Frees native resources.
+ /// </summary>
+ /// <remarks>
+ /// <seealso cref="CustomTypeMarshallerFeatures.UnmanagedResources"/>
+ /// </remarks>
+ public void FreeNative()
+ {
+ Marshal.FreeCoTaskMem(_allocatedMemory);
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs
index 7089b635941..d5f7fd9f7f1 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs
@@ -198,15 +198,6 @@ namespace Microsoft.Interop
{
try
{
- // TODO: Remove once helper types (like ArrayMarshaller) are part of the runtime
- // This check is to help with enabling the source generator for runtime libraries without making each
- // library directly reference System.Memory and System.Runtime.CompilerServices.Unsafe unless it needs to
- if (p.MarshallingAttributeInfo is MissingSupportMarshallingInfo
- && (environment.TargetFramework == TargetFramework.Net && environment.TargetFrameworkVersion.Major >= 7))
- {
- throw new MarshallingNotSupportedException(p, this);
- }
-
return new BoundGenerator(p, generatorFactory.Create(p, this));
}
catch (MarshallingNotSupportedException e)
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
index f53c7b82bdc..7165e9cfc3f 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
@@ -798,11 +798,11 @@ namespace Microsoft.Interop
INamedTypeSymbol? arrayMarshaller;
if (elementType is IPointerTypeSymbol { PointedAtType: ITypeSymbol pointedAt })
{
- arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_GeneratedMarshalling_PtrArrayMarshaller_Metadata)?.Construct(pointedAt);
+ arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_PointerArrayMarshaller_Metadata)?.Construct(pointedAt);
}
else
{
- arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_GeneratedMarshalling_ArrayMarshaller_Metadata)?.Construct(elementType);
+ arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_ArrayMarshaller_Metadata)?.Construct(elementType);
}
if (arrayMarshaller is null)
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
index 310299ed6d9..2e2f65c02c4 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
@@ -56,9 +56,9 @@ namespace Microsoft.Interop
public const string System_Runtime_InteropServices_MemoryMarshal = "System.Runtime.InteropServices.MemoryMarshal";
- public const string System_Runtime_InteropServices_GeneratedMarshalling_ArrayMarshaller_Metadata = "System.Runtime.InteropServices.GeneratedMarshalling.ArrayMarshaller`1";
+ public const string System_Runtime_InteropServices_ArrayMarshaller_Metadata = "System.Runtime.InteropServices.ArrayMarshaller`1";
- public const string System_Runtime_InteropServices_GeneratedMarshalling_PtrArrayMarshaller_Metadata = "System.Runtime.InteropServices.GeneratedMarshalling.PtrArrayMarshaller`1";
+ public const string System_Runtime_InteropServices_PointerArrayMarshaller_Metadata = "System.Runtime.InteropServices.PointerArrayMarshaller`1";
public const string System_Runtime_InteropServices_SafeHandle = "System.Runtime.InteropServices.SafeHandle";
diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
index 8a2fce98a39..53654b727d5 100644
--- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
+++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
@@ -99,7 +99,7 @@ namespace System.Runtime.InteropServices
public AllowReversePInvokeCallsAttribute() { }
}
[System.CLSCompliant(false)]
- [System.Runtime.InteropServices.CustomTypeMarshaller(typeof(string), BufferSize = 0x100,
+ [System.Runtime.InteropServices.CustomTypeMarshallerAttribute(typeof(string), BufferSize = 0x100,
Features = System.Runtime.InteropServices.CustomTypeMarshallerFeatures.UnmanagedResources
| System.Runtime.InteropServices.CustomTypeMarshallerFeatures.CallerAllocatedBuffer
| System.Runtime.InteropServices.CustomTypeMarshallerFeatures.TwoStageMarshalling )]
@@ -112,6 +112,27 @@ namespace System.Runtime.InteropServices
public string? ToManaged() { throw null; }
public void FreeNative() { }
}
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.CustomTypeMarshallerAttribute(typeof(System.Runtime.InteropServices.CustomTypeMarshallerAttribute.GenericPlaceholder[]),
+ System.Runtime.InteropServices.CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
+ Features = System.Runtime.InteropServices.CustomTypeMarshallerFeatures.UnmanagedResources
+ | System.Runtime.InteropServices.CustomTypeMarshallerFeatures.CallerAllocatedBuffer
+ | System.Runtime.InteropServices.CustomTypeMarshallerFeatures.TwoStageMarshalling)]
+ public unsafe ref struct ArrayMarshaller<T>
+ {
+ public ArrayMarshaller(int sizeOfNativeElement) { }
+ public ArrayMarshaller(T[]? array, int sizeOfNativeElement) { }
+ public ArrayMarshaller(T[]? array, System.Span<byte> buffer, int sizeOfNativeElement) { }
+ public System.ReadOnlySpan<T> GetManagedValuesSource() { throw null; }
+ public System.Span<T> GetManagedValuesDestination(int length) { throw null; }
+ public System.ReadOnlySpan<byte> GetNativeValuesSource(int length) { throw null; }
+ public System.Span<byte> GetNativeValuesDestination() { throw null; }
+ public ref byte GetPinnableReference() { throw null; }
+ public byte* ToNativeValue() { throw null; }
+ public void FromNativeValue(byte* value) { }
+ public T[]? ToManaged() { throw null; }
+ public void FreeNative() { }
+ }
public readonly partial struct ArrayWithOffset : System.IEquatable<System.Runtime.InteropServices.ArrayWithOffset>
{
private readonly object _dummy;
@@ -1054,6 +1075,27 @@ namespace System.Runtime.InteropServices
{
public OptionalAttribute() { }
}
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.CustomTypeMarshallerAttribute(typeof(System.Runtime.InteropServices.CustomTypeMarshallerAttribute.GenericPlaceholder*[]),
+ System.Runtime.InteropServices.CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
+ Features = System.Runtime.InteropServices.CustomTypeMarshallerFeatures.UnmanagedResources
+ | System.Runtime.InteropServices.CustomTypeMarshallerFeatures.CallerAllocatedBuffer
+ | System.Runtime.InteropServices.CustomTypeMarshallerFeatures.TwoStageMarshalling)]
+ public unsafe ref struct PointerArrayMarshaller<T> where T : unmanaged
+ {
+ public PointerArrayMarshaller(int sizeOfNativeElement) { }
+ public PointerArrayMarshaller(T*[]? array, int sizeOfNativeElement) { }
+ public PointerArrayMarshaller(T*[]? array, System.Span<byte> buffer, int sizeOfNativeElement) { }
+ public System.ReadOnlySpan<IntPtr> GetManagedValuesSource() { throw null; }
+ public System.Span<IntPtr> GetManagedValuesDestination(int length) { throw null; }
+ public System.ReadOnlySpan<byte> GetNativeValuesSource(int length) { throw null; }
+ public System.Span<byte> GetNativeValuesDestination() { throw null; }
+ public ref byte GetPinnableReference() { throw null; }
+ public byte* ToNativeValue() { throw null; }
+ public void FromNativeValue(byte* value) { }
+ public T*[]? ToManaged() { throw null; }
+ public void FreeNative() { }
+ }
public enum PosixSignal
{
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
@@ -1375,7 +1417,7 @@ namespace System.Runtime.InteropServices
public string? EntryPoint;
}
[System.CLSCompliant(false)]
- [System.Runtime.InteropServices.CustomTypeMarshaller(typeof(string), BufferSize = 0x100,
+ [System.Runtime.InteropServices.CustomTypeMarshallerAttribute(typeof(string), BufferSize = 0x100,
Features = System.Runtime.InteropServices.CustomTypeMarshallerFeatures.UnmanagedResources
| System.Runtime.InteropServices.CustomTypeMarshallerFeatures.CallerAllocatedBuffer
| System.Runtime.InteropServices.CustomTypeMarshallerFeatures.TwoStageMarshalling )]
@@ -1389,7 +1431,7 @@ namespace System.Runtime.InteropServices
public void FreeNative() { }
}
[System.CLSCompliant(false)]
- [System.Runtime.InteropServices.CustomTypeMarshaller(typeof(string), BufferSize = 0x100,
+ [System.Runtime.InteropServices.CustomTypeMarshallerAttribute(typeof(string), BufferSize = 0x100,
Features = System.Runtime.InteropServices.CustomTypeMarshallerFeatures.UnmanagedResources
| System.Runtime.InteropServices.CustomTypeMarshallerFeatures.CallerAllocatedBuffer
| System.Runtime.InteropServices.CustomTypeMarshallerFeatures.TwoStageMarshalling )]
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj
index b8e9081def8..629c77c4b34 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj
+++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj
@@ -10,7 +10,4 @@
<DefineConstants>$(DefineConstants);LIBRARYIMPORT_GENERATOR_TEST</DefineConstants>
</PropertyGroup>
- <ItemGroup>
- <Compile Include="$(LibrariesProjectRoot)Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs" Link="ArrayMarshaller.cs" />
- </ItemGroup>
</Project>