diff --git a/.editorconfig b/.editorconfig
index 598d07adf41..15658bab8d0 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -154,9 +154,6 @@ csharp_space_between_square_brackets = false
# License header
file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license.
-# Marshaller type must have CustomTypeMarshallerAttribute attribute
-dotnet_diagnostic.SYSLIB1056.severity = silent
-
# C++ Files
[*.{cpp,h,in}]
curly_bracket_next_line = true
diff --git a/docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md b/docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md
index ee1da9ff467..c1306a55da5 100644
--- a/docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md
+++ b/docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md
@@ -97,114 +97,94 @@ namespace System.Runtime.InteropServices.Marshalling;
- Ref = In | Out,
- }
++
++
+ ///
-+ /// Define features for a custom type marshaller.
++ /// An enumeration representing the different marshalling scenarios in our marshalling model.
+ ///
-+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
-+ public sealed class CustomTypeMarshallerFeaturesAttribute : Attribute
++ public enum MarshalMode
+ {
+ ///
-+ /// Desired caller buffer size for the marshaller.
++ /// All scenarios. A marshaller specified with this scenario will be used if there is not a specific
++ /// marshaller specified for a given usage scenario.
+ ///
-+ public int BufferSize { get; set; }
++ Default,
++ ///
++ /// By-value and in parameters in managed-to-unmanaged scenarios, like P/Invoke.
++ ///
++ ManagedToUnmanagedIn,
++ ///
++ /// ref parameters in managed-to-unmanaged scenarios, like P/Invoke.
++ ///
++ ManagedToUnmanagedRef,
++ ///
++ /// out parameters in managed-to-unmanaged scenarios, like P/Invoke.
++ ///
++ ManagedToUnmanagedOut,
++ ///
++ /// By-value and in parameters in unmanaged-to-managed scenarios, like Reverse P/Invoke.
++ ///
++ UnmanagedToManagedIn,
++ ///
++ /// ref parameters in unmanaged-to-managed scenarios, like Reverse P/Invoke.
++ ///
++ UnmanagedToManagedRef,
++ ///
++ /// out parameters in unmanaged-to-managed scenarios, like Reverse P/Invoke.
++ ///
++ UnmanagedToManagedOut,
++ ///
++ /// Elements of arrays passed with in or by-value in interop scenarios.
++ ///
++ ElementIn,
++ ///
++ /// Elements of arrays passed with ref or passed by-value with both and in interop scenarios.
++ ///
++ ElementRef,
++ ///
++ /// Elements of arrays passed with out or passed by-value with only in interop scenarios.
++ ///
++ ElementOut
+ }
+
-+
+ ///
-+ /// Base class attribute for custom marshaller attributes.
++ /// Attribute to indicate an entry point type for defining a marshaller.
+ ///
-+ ///
-+ /// Use a base class here to allow doing ManagedToUnmanagedMarshallersAttribute.GenericPlaceholder, etc. without having 3 + separate placeholder types.
-+ /// For the following attribute types, any marshaller types that are provided will be validated by an analyzer to have the + correct members to prevent
-+ /// developers from accidentally typoing a member like Free() and causing memory leaks.
-+ ///
-+ public abstract class CustomUnmanagedTypeMarshallersAttributeBase : Attribute
++ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple = true)]
++ public sealed class CustomMarshallerAttribute : Attribute
+ {
+ ///
++ /// Create a instance.
++ ///
++ /// Managed type to marshal.
++ /// Marshalling mode.
++ /// Type used for marshalling.
++ public CustomMarshallerAttribute(Type managedType, MarshalMode marshalMode, Type marshallerType)
++ {
++ ManagedType = managedType;
++ MarshalMode = marshalMode;
++ MarshallerType = marshallerType;
++ }
++
++ public Type ManagedType { get; }
++
++ public MarshalMode MarshalMode { get; }
++
++ public Type MarshallerType { get; }
++
++ ///
+ /// Placeholder type for generic parameter
+ ///
-+ public sealed class GenericPlaceholder { }
++ public struct GenericPlaceholder
++ {
++ }
+ }
+
+ ///
-+ /// Specify marshallers used in the managed to unmanaged direction (that is, P/Invoke)
++ /// Specifies that this marshaller entry-point type is a contiguous collection marshaller.
+ ///
-+ [AttributeUsage(AttributeTargets.Class)]
-+ public sealed class ManagedToUnmanagedMarshallersAttribute : CustomUnmanagedTypeMarshallersAttributeBase
-+ {
-+ ///
-+ /// Create instance of .
-+ ///
-+ /// Managed type to marshal
-+ public ManagedToUnmanagedMarshallersAttribute(Type managedType) { }
-+
-+ ///
-+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the in keyword.
-+ ///
-+ public Type? InMarshaller { get; set; }
-+
-+ ///
-+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the ref keyword.
-+ ///
-+ public Type? RefMarshaller { get; set; }
-+
-+ ///
-+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the out keyword.
-+ ///
-+ public Type? OutMarshaller { get; set; }
-+ }
-+
-+ ///
-+ /// Specify marshallers used in the unmanaged to managed direction (that is, Reverse P/Invoke)
-+ ///
-+ [AttributeUsage(AttributeTargets.Class)]
-+ public sealed class UnmanagedToManagedMarshallersAttribute : CustomUnmanagedTypeMarshallersAttributeBase
-+ {
-+ ///
-+ /// Create instance of .
-+ ///
-+ /// Managed type to marshal
-+ public UnmanagedToManagedMarshallersAttribute(Type managedType) { }
-+
-+ ///
-+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the in keyword.
-+ ///
-+ public Type? InMarshaller { get; set; }
-+
-+ ///
-+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the ref keyword.
-+ ///
-+ public Type? RefMarshaller { get; set; }
-+
-+ ///
-+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the out keyword.
-+ ///
-+ public Type? OutMarshaller { get; set; }
-+ }
-+
-+ ///
-+ /// Specify marshaller for array-element marshalling and default struct field marshalling.
-+ ///
-+ [AttributeUsage(AttributeTargets.Class)]
-+ public sealed class ElementMarshallerAttribute : CustomUnmanagedTypeMarshallersAttributeBase
-+ {
-+ ///
-+ /// Create instance of .
-+ ///
-+ /// Managed type to marshal
-+ /// Marshaller type to use for marshalling .
-+ public ElementMarshallerAttribute(Type managedType, Type elementMarshaller) { }
-+ }
-+
-+ ///
-+ /// Specifies that a particular generic parameter is the collection element's unmanaged type.
-+ ///
-+ ///
-+ /// If this attribute is provided on a generic parameter of a marshaller, then the generator will assume
-+ /// that it is a linear collection marshaller.
-+ ///
-+ [AttributeUsage(AttributeTargets.GenericParameter)]
-+ public sealed class ElementUnmanagedTypeAttribute : Attribute
++ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
++ public sealed class ContiguousCollectionMarshallerAttribute : Attribute
+ {
+ }
```
@@ -264,9 +244,9 @@ The element type of the `Span` for the caller-allocated buffer can be any type t
[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(ManagedToNative))]
static class TMarshaller
{
- [CustomTypeMarshallerFeatures(BufferSize = 0x200)]
public static class ManagedToNative
{
+ public static int BufferSize { get; }
public static TNative ConvertToUnmanaged(TManaged managed, Span callerAllocatedBuffer); // Can throw exceptions
public static void Free(TNative unmanaged); // Optional. Should not throw exceptions
@@ -294,7 +274,7 @@ static class TMarshaller
### Stateless Unmanaged->Managed with Guaranteed Unmarshalling
-This shape directs the generator to emit the `ConvertToManagedGuaranteed` call in the "GuaranteedUnmarshal" phase of marshalling.
+This shape directs the generator to emit the `ConvertToManagedFinally` call in the "GuaranteedUnmarshal" phase of marshalling.
```csharp
[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(NativeToManaged))]
@@ -303,7 +283,7 @@ static class TMarshaller
{
public static class NativeToManaged
{
- public static TManaged ConvertToManagedGuaranteed(TNative unmanaged); // Should not throw exceptions
+ public static TManaged ConvertToManagedFinally(TNative unmanaged); // Should not throw exceptions
public static void Free(TNative unmanaged); // Optional. Should not throw exceptions
}
@@ -347,7 +327,7 @@ static class TMarshaller
public TNative ToUnmanaged(); // Can throw exceptions.
- public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions.
+ public void OnInvoked(); // Optional. Should not throw exceptions.
public void Free(); // Should not throw exceptions.
}
@@ -363,9 +343,9 @@ The element type of the `Span` for the caller-allocated buffer can be any type t
[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(ManagedToNative))]
static class TMarshaller
{
- [CustomTypeMarshallerFeatures(BufferSize = 0x200)]
public struct ManagedToNative // Can be ref struct
{
+ public static int BufferSize { get; }
public ManagedToNative(); // Optional, can throw exceptions.
public void FromManaged(TManaged managed, Span buffer); // Can throw exceptions.
@@ -376,7 +356,7 @@ static class TMarshaller
public TNative ToUnmanaged(); // Can throw exceptions.
- public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions.
+ public void OnInvoked(); // Optional. Should not throw exceptions.
public void Free(); // Should not throw exceptions.
}
@@ -418,7 +398,7 @@ static class TMarshaller
public void FromUnmanaged(TNative native); // Should not throw exceptions.
- public TManaged ToManagedGuaranteed(); // Should not throw exceptions.
+ public TManaged ToManagedFinally(); // Should not throw exceptions.
public void Free(); // Should not throw exceptions.
}
@@ -455,7 +435,7 @@ struct TCollection
}
```
-A collection marshaller for a managed type will have similar generics handling as the value marshaller case; however, there is one difference. A collection marshaller must have an additional generic parameter with the `ElementUnmanagedTypeAttribute`. This parameter can optionally be constrained to `: unmanaged` (but the system will not require this). The attributed parameter will be filled in with a generics-compatible representation of the unmanaged type for the collection's element type (`nint` will be used when the native type is a pointer type).
+A collection marshaller must have the `ContiguousCollectionMarshallerAttribute` applied to the entry-point type. A collection marshaller for a managed type will have similar generics handling as the value marshaller case; however, there is one difference. A collection marshaller must have an additional generic parameter at the end of the generic parameter list. This parameter can optionally be constrained to `: unmanaged` (but the system will not require this). The additional parameter will be filled in with a generics-compatible representation of the unmanaged type for the collection's element type (`nint` will be used when the native type is a pointer type).
The type `TNative` can be any `unmanaged` type. It represents whatever unmanaged type the marshaller marshals the managed type to.
@@ -463,9 +443,11 @@ The type `TNative` can be any `unmanaged` type. It represents whatever unmanaged
### Stateless Managed->Unmanaged
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ElementIn, typeof(ManagedToNative))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public static class ManagedToNative
{
@@ -487,13 +469,14 @@ static class TMarshaller w
The element type of the `Span` for the caller-allocated buffer can be any type that guarantees any alignment requirements, including `TUnmanagedElement`.
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ElementIn, typeof(ManagedToNative))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
- [CustomTypeMarshallerFeatures(BufferSize = 0x200)]
public static class ManagedToNative
{
+ public static int BufferSize { get; }
public static TNative AllocateContainerForUnmanagedElements(TCollection managed, Span buffer, out int numElements); // Can throw exceptions
public static ReadOnlySpan GetManagedValuesSource(TCollection managed); // Can throw exceptions
@@ -511,9 +494,11 @@ static class TMarshaller w
### Stateless Unmanaged->Managed
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ElementOut, typeof(NativeToManaged))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public static class NativeToManaged
{
@@ -531,16 +516,16 @@ static class TMarshaller w
### Stateless Unmanaged->Managed with Guaranteed Unmarshalling
-This shape directs the generator to emit the `ConvertToManagedGuaranteed` call in the "GuaranteedUnmarshal" phase of marshalling.
+This shape directs the generator to emit the `ConvertToManagedFinally` call in the "GuaranteedUnmarshal" phase of marshalling.
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public static class NativeToManaged
{
- public static TCollection AllocateContainerForManagedElementsGuaranteed(TNative unmanaged, int length); // Should not throw exceptions other than OutOfMemoryException.
+ public static TCollection AllocateContainerForManagedElementsFinally(TNative unmanaged, int length); // Should not throw exceptions other than OutOfMemoryException.
public static Span GetManagedValuesDestination(T[] managed) => managed; // Can throw exceptions
@@ -554,10 +539,11 @@ static class TMarshaller w
### Stateless Bidirectional
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))]
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))]
-[ElementMarshaller(typeof(TManaged<,,,...>), typeof(Bidirectional))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ElementRef, typeof(Bidirectional))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public static class Bidirectional
{
@@ -572,9 +558,10 @@ static class TMarshaller w
### Stateful Managed->Unmanaged
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public struct ManagedToNative // Can be ref struct
{
@@ -592,7 +579,7 @@ static class TMarshaller w
public static ref TOther GetPinnableReference(TCollection collection); // Optional. Can throw exceptions. Result pinnned and passed to Invoke.
- public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions.
+ public void OnInvoked(); // Optional. Should not throw exceptions.
}
}
@@ -602,13 +589,14 @@ static class TMarshaller w
The element type of the `Span` for the caller-allocated buffer can be any type that guarantees any alignment requirements.
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
- [CustomTypeMarshallerFeatures(BufferSize = 0x200)]
public struct ManagedToNative // Can be ref struct
{
+ public static int BufferSize { get; }
+
public ManagedToNative(); // Optional, can throw exceptions.
public void FromManaged(TCollection collection, Span buffer); // Can throw exceptions.
@@ -623,7 +611,7 @@ static class TMarshaller w
public static ref TOther GetPinnableReference(TCollection collection); // Optional. Can throw exceptions. Result pinnned and passed to Invoke.
- public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions.
+ public void OnInvoked(); // Optional. Should not throw exceptions.
}
}
@@ -632,9 +620,10 @@ static class TMarshaller w
### Stateful Unmanaged->Managed
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public struct NativeToManaged // Can be ref struct
{
@@ -657,9 +646,9 @@ static class TMarshaller w
### Stateful Unmanaged->Managed with Guaranteed Unmarshalling
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))]
-[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public struct NativeToManaged // Can be ref struct
{
@@ -671,7 +660,7 @@ static class TMarshaller w
public Span GetManagedValuesDestination(int length); // Can throw exceptions.
- public TCollection ToManagedGuaranteed(); // Can throw exceptions
+ public TCollection ToManagedFinally(); // Can throw exceptions
public void Free(); // Optional. Should not throw exceptions.
}
@@ -681,9 +670,10 @@ static class TMarshaller w
### Stateful Bidirectional
```csharp
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))]
-[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))]
-static class TMarshaller where TUnmanagedElement : unmanaged
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
+[CustomMarshaller(typeof(TCollection<,,,...>), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))]
+[ContiguousCollectionMarshaller]
+static class TMarshaller where TUnmanagedElement : unmanaged
{
public struct Bidirectional // Can be ref struct
{
@@ -702,7 +692,7 @@ There's a few optional members in the above shapes. This section explains what t
The `Free` method on each shape supports releasing any unmanaged (or managed in the stateful shapes) resources. This method is optional as the `Free` method is required to be called in a `finally` clause and emitting a `try-finally` block with only method calls to empty methods puts a lot of stress on the JIT to inline all of the methods and realize that they are no-ops to remove the `finally` clause. Additionally, just having the `try-finally` block wrapping the main code can cause some de-optimizations.
-### NotifyInvokeSucceeded method
+### OnInvoked method
This method is called after a stub successfully invokes the target code (unmanaged code in a P/Invoke scenario, managed code in a Reverse P/Invoke scenario). As this method would be called in a very large majority of cases in P/Invoke-style scenarios and has only limited utility (its main use is to provide a good place to call `GC.KeepAlive` that does not require a `try-finally` block), we decided to make it optional.
@@ -731,7 +721,7 @@ The marshaller type must be an entry-point marshaller type as defined above and
- The type must either be:
- Non-generic
- A closed generic
- - An open generic with as many generic parameters with compatible constraints as the managed type (excluding up to one generic parameter with the `ElementUnmanagedTypeAttribute`)
+ - An open generic with as many generic parameters with compatible constraints as the managed type (excluding one generic parameter if the marshaller has the `ContiguousCollectionMarshallerAttribute` attribute)
- If used in `NativeMarshallingAttribute`, the type should be at least as visible as the managed type.
Passing size info for parameters will be based to the [V1 design](SpanMarshallers.md#providing-additional-data-for-collection-marshalling) and the properties/fields on `MarshalUsingAttribute` will remain unchanged.
diff --git a/eng/generators.targets b/eng/generators.targets
index cc04480a7ff..ac01adc5cc4 100644
--- a/eng/generators.targets
+++ b/eng/generators.targets
@@ -69,8 +69,6 @@
-
-
diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs
index cc830f8da21..b313fb36b05 100644
--- a/src/libraries/Common/src/Interop/Interop.Ldap.cs
+++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs
@@ -49,7 +49,7 @@ namespace System.DirectoryServices.Protocols
public int packageListLength;
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(SEC_WINNT_AUTH_IDENTITY_EX), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))]
+ [CustomMarshaller(typeof(SEC_WINNT_AUTH_IDENTITY_EX), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
internal static class Marshaller
{
public static Native ConvertToUnmanaged(SEC_WINNT_AUTH_IDENTITY_EX managed)
diff --git a/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs b/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs
index 8342b5c405a..e58a0b497dc 100644
--- a/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs
+++ b/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs
@@ -40,7 +40,7 @@ internal static partial class Interop
internal uint nStartPage;
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public static Native ConvertToUnmanaged(CRYPTUI_VIEWCERTIFICATE_STRUCTW managed) => new(managed);
@@ -152,7 +152,7 @@ internal static partial class Interop
internal IntPtr hSelectedCertStore;
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(CRYPTUI_SELECTCERTIFICATE_STRUCTW), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(CRYPTUI_SELECTCERTIFICATE_STRUCTW), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public static Native ConvertToUnmanaged(CRYPTUI_SELECTCERTIFICATE_STRUCTW managed) => new(managed);
diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs
index 14306c82e36..ad97442aced 100644
--- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs
+++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs
@@ -56,7 +56,7 @@ internal static partial class Interop
uint modifiers);
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(StringBuilder), Scenario.ManagedToUnmanagedIn, typeof(SimpleStringBufferMarshaller))]
+ [CustomMarshaller(typeof(StringBuilder), MarshalMode.ManagedToUnmanagedIn, typeof(SimpleStringBufferMarshaller))]
private static unsafe class SimpleStringBufferMarshaller
{
public static void* ConvertToUnmanaged(StringBuilder builder)
diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs
index fe86bda7758..1cbdfa79d59 100644
--- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs
+++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs
@@ -262,7 +262,7 @@ internal static partial class Interop
[MarshalAs(UnmanagedType.Bool)]
public bool AutoLoginIfChallenged;
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(WINHTTP_AUTOPROXY_OPTIONS), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(WINHTTP_AUTOPROXY_OPTIONS), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public static Native ConvertToUnmanaged(WINHTTP_AUTOPROXY_OPTIONS managed) => new(managed);
diff --git a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs
index 34c29cf3173..3c3e831fac9 100644
--- a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs
+++ b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs
@@ -28,7 +28,7 @@ internal static partial class Interop
private ushort wReserved1;
private ushort dwSupport;
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(WAVEOUTCAPS), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(WAVEOUTCAPS), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public static Native ConvertToUnmanaged(WAVEOUTCAPS managed) => new(managed);
diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WinsockBSD.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WinsockBSD.cs
index 54bb6149a02..0633d7ab896 100644
--- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WinsockBSD.cs
+++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WinsockBSD.cs
@@ -75,7 +75,7 @@ internal static partial class Interop
internal byte[] MulticastAddress; // IP address of group.
internal int InterfaceIndex; // Local interface index.
- [CustomMarshaller(typeof(IPv6MulticastRequest), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(IPv6MulticastRequest), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public static Native ConvertToUnmanaged(IPv6MulticastRequest managed) => new(managed);
diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs
index 49015a133a3..f3aca7e7595 100644
--- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs
+++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs
@@ -703,7 +703,7 @@ namespace Microsoft.Win32
public uint Type;
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(EvtStringVariant), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(EvtStringVariant), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public static Native ConvertToUnmanaged(EvtStringVariant managed) => new(managed);
diff --git a/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs b/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs
index 140356c7967..8b754d321fa 100644
--- a/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs
+++ b/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs
@@ -188,7 +188,7 @@ internal static partial class Interop
internal int fwType;
#if NET7_0_OR_GREATER
- [CustomMarshaller(typeof(DOCINFO), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))]
+ [CustomMarshaller(typeof(DOCINFO), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
public static class Marshaller
{
public static Native ConvertToUnmanaged(DOCINFO managed) => new(managed);
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 a079ceb5f11..d978ef0b8c4 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
@@ -872,10 +872,12 @@
+
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomMarshallerAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomMarshallerAttribute.cs
new file mode 100644
index 00000000000..a19740e2983
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomMarshallerAttribute.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+#nullable enable
+
+namespace System.Runtime.InteropServices.Marshalling
+{
+ ///
+ /// Attribute to indicate an entry point type for defining a marshaller.
+ ///
+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple = true)]
+ public sealed class CustomMarshallerAttribute : Attribute
+ {
+ ///
+ /// Create a instance.
+ ///
+ /// Managed type to marshal.
+ /// The marshalling mode this attribute applies to.
+ /// Type used for marshalling.
+ public CustomMarshallerAttribute(Type managedType, MarshalMode marshalMode, Type marshallerType)
+ {
+ ManagedType = managedType;
+ MarshalMode = marshalMode;
+ MarshallerType = marshallerType;
+ }
+
+ ///
+ /// The managed type to marshal.
+ ///
+ public Type ManagedType { get; }
+
+ ///
+ /// The marshalling mode this attribute applies to.
+ ///
+ public MarshalMode MarshalMode { get; }
+
+ ///
+ /// Type used for marshalling.
+ ///
+ public Type MarshallerType { get; }
+
+ ///
+ /// Placeholder type for generic parameter
+ ///
+ public struct GenericPlaceholder
+ {
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Scenario.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/MarshalMode.cs
similarity index 81%
rename from src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Scenario.cs
rename to src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/MarshalMode.cs
index 485d2418706..5d7a79756e2 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Scenario.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/MarshalMode.cs
@@ -4,22 +4,17 @@
#if MICROSOFT_INTEROP_SOURCEGENERATION
namespace Microsoft.Interop
#else
-namespace System.Runtime.InteropServices
+namespace System.Runtime.InteropServices.Marshalling
#endif
{
///
- /// An enumeration representing the different marshalling scenarios in our marshalling model.
+ /// An enumeration representing the different marshalling modes in our marshalling model.
///
-#if LIBRARYIMPORT_GENERATOR_TEST || MICROSOFT_INTEROP_SOURCEGENERATION
- public
-#else
- internal
-#endif
- enum Scenario
+ public enum MarshalMode
{
///
- /// All scenarios. A marshaller specified with this scenario will be used if there is not a specific
- /// marshaller specified for a given usage scenario.
+ /// All modes. A marshaller specified with this mode will be used if there is not a specific
+ /// marshaller specified for a given usage mode.
///
Default,
///
diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs
index 6b6e1e1589a..8e380eeba24 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs
@@ -500,6 +500,13 @@ namespace Microsoft.Interop.Analyzers
if (!hasCustomTypeMarshallerAttribute)
{
+ if (ManualTypeMarshallingHelper.HasEntryPointMarshallerAttribute(entryType))
+ {
+ // TEMPORARY: Don't analyze V2 analyzers in this method for now.
+ // We'll add support soon, but for now just don't emit warnings to use the V1 marshaller design
+ // when using the V2 design.
+ return;
+ }
context.ReportDiagnostic(
attributeData.CreateDiagnostic(
NativeTypeMustHaveCustomTypeMarshallerAttributeRule,
diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs
index c262c2e0017..e32ccc145f6 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs
@@ -358,13 +358,13 @@ namespace Microsoft.Interop
// Since the char type in an array will not be part of the P/Invoke signature, we can
// use the regular blittable marshaller in all cases.
new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true),
- new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, Scenario.ElementIn, Scenario.ElementRef, Scenario.ElementOut));
+ new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut));
// We don't need to include the later generator factories for collection elements
// as the later generator factories only apply to parameters.
generatorFactory = new AttributedMarshallingModelGeneratorFactory(
generatorFactory,
elementFactory,
- new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, Scenario.ManagedToUnmanagedIn, Scenario.ManagedToUnmanagedRef, Scenario.ManagedToUnmanagedOut));
+ new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ManagedToUnmanagedIn, MarshalMode.ManagedToUnmanagedRef, MarshalMode.ManagedToUnmanagedOut));
generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory);
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs
index 2f45d23393e..568fc4ff111 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs
@@ -24,32 +24,32 @@ namespace Microsoft.Interop
MarshallingInfo? CollectionElementMarshallingInfo);
public readonly record struct CustomTypeMarshallers(
- ImmutableDictionary Scenarios)
+ ImmutableDictionary Modes)
{
- public CustomTypeMarshallerData GetScenarioOrDefault(Scenario scenario)
+ public CustomTypeMarshallerData GetModeOrDefault(MarshalMode mode)
{
CustomTypeMarshallerData data;
- if (Scenarios.TryGetValue(scenario, out data))
+ if (Modes.TryGetValue(mode, out data))
return data;
- if (Scenarios.TryGetValue(Scenario.Default, out data))
+ if (Modes.TryGetValue(MarshalMode.Default, out data))
return data;
// TODO: Hard failure based on previous implementation
throw new InvalidOperationException();
}
- public bool TryGetScenarioOrDefault(Scenario scenario, out CustomTypeMarshallerData data)
+ public bool TryGetModeOrDefault(MarshalMode mode, out CustomTypeMarshallerData data)
{
- if (Scenarios.TryGetValue(scenario, out data))
+ if (Modes.TryGetValue(mode, out data))
return true;
- return Scenarios.TryGetValue(Scenario.Default, out data);
+ return Modes.TryGetValue(MarshalMode.Default, out data);
}
- public bool IsDefinedOrDefault(Scenario scenario)
+ public bool IsDefinedOrDefault(MarshalMode mode)
{
- return Scenarios.ContainsKey(scenario) || Scenarios.ContainsKey(Scenario.Default);
+ return Modes.ContainsKey(mode) || Modes.ContainsKey(MarshalMode.Default);
}
}
@@ -73,7 +73,7 @@ namespace Microsoft.Interop
public static bool IsLinearCollectionEntryPoint(INamedTypeSymbol entryPointType)
{
return entryPointType.IsGenericType
- && entryPointType.TypeParameters.Last().GetAttributes().Any(attr => attr.AttributeClass.ToDisplayString() == TypeNames.ElementUnmanagedTypeAttribute);
+ && entryPointType.GetAttributes().Any(attr => attr.AttributeClass.ToDisplayString() == TypeNames.ContiguousCollectionMarshallerAttribute);
}
public static bool HasEntryPointMarshallerAttribute(ITypeSymbol entryPointType)
@@ -116,7 +116,7 @@ namespace Microsoft.Interop
// We expect a callback for getting the element marshalling info when handling linear collection marshalling
Debug.Assert(!isLinearCollectionMarshalling || getMarshallingInfoForElement is not null);
- Dictionary scenarios = new();
+ Dictionary modes = new();
foreach (AttributeData attr in attrs)
{
Debug.Assert(attr.ConstructorArguments.Length == 3);
@@ -136,7 +136,7 @@ namespace Microsoft.Interop
&& !compilation.HasImplicitConversion(managedType, managedTypeInst))
return false;
- var marshallerScenario = (Scenario)attr.ConstructorArguments[1].Value!;
+ var marshalMode = (MarshalMode)attr.ConstructorArguments[1].Value!;
ITypeSymbol? marshallerTypeOnAttr = attr.ConstructorArguments[2].Value as ITypeSymbol;
if (marshallerTypeOnAttr is null)
@@ -168,51 +168,51 @@ namespace Microsoft.Interop
}
// TODO: We can probably get rid of MarshallingDirection and just use Scenario instead
- MarshallingDirection direction = marshallerScenario switch
+ MarshallingDirection direction = marshalMode switch
{
- Scenario.Default
+ MarshalMode.Default
=> MarshallingDirection.Bidirectional,
- Scenario.ManagedToUnmanagedIn
- or Scenario.UnmanagedToManagedOut
+ MarshalMode.ManagedToUnmanagedIn
+ or MarshalMode.UnmanagedToManagedOut
=> MarshallingDirection.ManagedToUnmanaged,
- Scenario.ManagedToUnmanagedOut
- or Scenario.UnmanagedToManagedIn
+ MarshalMode.ManagedToUnmanagedOut
+ or MarshalMode.UnmanagedToManagedIn
=> MarshallingDirection.UnmanagedToManaged,
- Scenario.ManagedToUnmanagedRef
- or Scenario.UnmanagedToManagedRef
+ MarshalMode.ManagedToUnmanagedRef
+ or MarshalMode.UnmanagedToManagedRef
=> MarshallingDirection.Bidirectional,
- Scenario.ElementIn
- or Scenario.ElementRef
- or Scenario.ElementOut
+ MarshalMode.ElementIn
+ or MarshalMode.ElementRef
+ or MarshalMode.ElementOut
=> MarshallingDirection.Bidirectional,
_ => throw new UnreachableException()
};
- // TODO: Report invalid shape for scenario
- // Skip checking for bidirectional support for Default scenario - always take / store marshaller data
+ // TODO: Report invalid shape for mode
+ // Skip checking for bidirectional support for Default mode - always take / store marshaller data
CustomTypeMarshallerData? data = GetMarshallerDataForType(marshallerType, direction, managedType, isLinearCollectionMarshalling, compilation, getMarshallingInfoForElement);
- // TODO: Should we fire a diagnostic for duplicated scenarios or just take the last one?
+ // TODO: Should we fire a diagnostic for duplicated modes or just take the last one?
if (data is null
- || scenarios.ContainsKey(marshallerScenario))
+ || modes.ContainsKey(marshalMode))
{
continue;
}
- scenarios.Add(marshallerScenario, data.Value);
+ modes.Add(marshalMode, data.Value);
}
- if (scenarios.Count == 0)
+ if (modes.Count == 0)
return false;
marshallers = new CustomTypeMarshallers()
{
- Scenarios = scenarios.ToImmutableDictionary()
+ Modes = modes.ToImmutableDictionary()
};
return true;
@@ -392,10 +392,10 @@ namespace Microsoft.Interop
}
else
{
- // Native type is the first parameter of ConvertToManaged or ConvertToManagedGuaranteed
- if (methods.ToManagedGuaranteed is not null)
+ // Native type is the first parameter of ConvertToManaged or ConvertToManagedFinally
+ if (methods.ToManagedFinally is not null)
{
- nativeType = methods.ToManagedGuaranteed.Parameters[0].Type;
+ nativeType = methods.ToManagedFinally.Parameters[0].Type;
}
else if (methods.ToManaged is not null)
{
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallerShape.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallerShape.cs
index ec37715128b..aa22bcff19f 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallerShape.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallerShape.cs
@@ -22,7 +22,7 @@ namespace Microsoft.Interop
ToManaged = 0x10,
GuaranteedUnmarshal = 0x20,
Free = 0x40,
- NotifyInvokeSucceeded = 0x80,
+ OnInvoked = 0x80,
}
public static class ShapeMemberNames
@@ -36,7 +36,7 @@ namespace Microsoft.Interop
public static class Stateless
{
public const string ConvertToManaged = nameof(ConvertToManaged);
- public const string ConvertToManagedGuaranteed = nameof(ConvertToManagedGuaranteed);
+ public const string ConvertToManagedFinally = nameof(ConvertToManagedFinally);
public const string ConvertToUnmanaged = nameof(ConvertToUnmanaged);
}
@@ -47,11 +47,11 @@ namespace Microsoft.Interop
public const string ToUnmanaged = nameof(ToUnmanaged);
// Unmanaged to managed
public const string ToManaged = nameof(ToManaged);
- public const string ToManagedGuaranteed = nameof(ToManagedGuaranteed);
+ public const string ToManagedFinally = nameof(ToManagedFinally);
public const string FromUnmanaged = nameof(FromUnmanaged);
// Optional features
public const string Free = nameof(Free);
- public const string NotifyInvokeSucceeded = nameof(NotifyInvokeSucceeded);
+ public const string OnInvoked = nameof(OnInvoked);
}
}
@@ -66,7 +66,7 @@ namespace Microsoft.Interop
// Unmanaged to managed
public const string AllocateContainerForManagedElements = nameof(AllocateContainerForManagedElements);
- public const string AllocateContainerForManagedElementsGuaranteed = nameof(AllocateContainerForManagedElementsGuaranteed);
+ public const string AllocateContainerForManagedElementsFinally = nameof(AllocateContainerForManagedElementsFinally);
public const string GetManagedValuesDestination = nameof(GetManagedValuesDestination);
public const string GetUnmanagedValuesSource = nameof(GetUnmanagedValuesSource);
}
@@ -82,11 +82,11 @@ namespace Microsoft.Interop
public const string GetManagedValuesDestination = nameof(GetManagedValuesDestination);
public const string GetUnmanagedValuesSource = nameof(GetUnmanagedValuesSource);
public const string ToManaged = nameof(ToManaged);
- public const string ToManagedGuaranteed = nameof(ToManagedGuaranteed);
+ public const string ToManagedFinally = nameof(ToManagedFinally);
public const string FromUnmanaged = nameof(FromUnmanaged);
// Optional features
public const string Free = nameof(Free);
- public const string NotifyInvokeSucceeded = nameof(NotifyInvokeSucceeded);
+ public const string OnInvoked = nameof(OnInvoked);
}
}
}
@@ -98,7 +98,7 @@ namespace Microsoft.Interop
public IMethodSymbol? ToUnmanaged;
public IMethodSymbol? ToUnmanagedWithBuffer;
public IMethodSymbol? ToManaged;
- public IMethodSymbol? ToManagedGuaranteed;
+ public IMethodSymbol? ToManagedFinally;
// Linear collection
public IMethodSymbol? ManagedValuesSource;
@@ -142,7 +142,7 @@ namespace Microsoft.Interop
// Unmanaged -> Managed
IMethodSymbol? allocateManaged = LinearCollection.AllocateContainerForManagedElements(marshallerType, managedType);
- IMethodSymbol? allocateManagedGuaranteed = LinearCollection.AllocateContainerForManagedElementsGuaranteed(marshallerType, managedType, spanOfT);
+ IMethodSymbol? allocateManagedGuaranteed = LinearCollection.AllocateContainerForManagedElementsFinally(marshallerType, managedType, spanOfT);
IMethodSymbol? managedDestination = LinearCollection.GetManagedValuesDestination(marshallerType, managedType, spanOfT);
IMethodSymbol? unmanagedSource = LinearCollection.GetUnmanagedValuesSource(marshallerType, readOnlySpanOfT);
if ((allocateManaged is not null || allocateManagedGuaranteed is not null)
@@ -158,7 +158,7 @@ namespace Microsoft.Interop
methods = methods with
{
ToManaged = allocateManaged,
- ToManagedGuaranteed = allocateManagedGuaranteed,
+ ToManagedFinally = allocateManagedGuaranteed,
ManagedValuesDestination = managedDestination,
UnmanagedValuesSource = unmanagedSource
};
@@ -178,8 +178,8 @@ namespace Microsoft.Interop
if (toManaged is not null)
shape |= MarshallerShape.ToManaged;
- IMethodSymbol? toManagedGuaranteed = Value.ConvertToManagedGuaranteed(marshallerType, managedType);
- if (toManagedGuaranteed is not null)
+ IMethodSymbol? toManagedFinally = Value.ConvertToManagedFinally(marshallerType, managedType);
+ if (toManagedFinally is not null)
shape |= MarshallerShape.GuaranteedUnmarshal;
methods = methods with
@@ -187,7 +187,7 @@ namespace Microsoft.Interop
ToUnmanaged = toUnmanaged,
ToUnmanagedWithBuffer = toUnmanagedWithBuffer,
ToManaged = toManaged,
- ToManagedGuaranteed = toManagedGuaranteed
+ ToManagedFinally = toManagedFinally
};
}
@@ -275,10 +275,10 @@ namespace Microsoft.Interop
&& SymbolEqualityComparer.Default.Equals(managedType, m.ReturnType));
}
- internal static IMethodSymbol? ConvertToManagedGuaranteed(ITypeSymbol type, ITypeSymbol managedType)
+ internal static IMethodSymbol? ConvertToManagedFinally(ITypeSymbol type, ITypeSymbol managedType)
{
- // static TManaged ConvertToManagedGuaranteed(TNative unmanaged)
- return type.GetMembers(ShapeMemberNames.Value.Stateless.ConvertToManagedGuaranteed)
+ // static TManaged ConvertToManagedFinally(TNative unmanaged)
+ return type.GetMembers(ShapeMemberNames.Value.Stateless.ConvertToManagedFinally)
.OfType()
.FirstOrDefault(m => m is { IsStatic: true, Parameters.Length: 1, ReturnsVoid: false }
&& SymbolEqualityComparer.Default.Equals(managedType, m.ReturnType));
@@ -349,9 +349,9 @@ namespace Microsoft.Interop
&& managedType.IsConstructedFromEqualTypes(m.ReturnType));
}
- internal static IMethodSymbol? AllocateContainerForManagedElementsGuaranteed(ITypeSymbol type, ITypeSymbol managedType, ITypeSymbol spanOfT)
+ internal static IMethodSymbol? AllocateContainerForManagedElementsFinally(ITypeSymbol type, ITypeSymbol managedType, ITypeSymbol spanOfT)
{
- // static TCollection AllocateContainerForManagedElementsGuaranteed(TNative unmanaged, int length);
+ // static TCollection AllocateContainerForManagedElementsFinally(TNative unmanaged, int length);
return type.GetMembers(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElements)
.OfType()
.FirstOrDefault(m => m is { IsStatic: true, Parameters.Length: 2, ReturnsVoid: false }
@@ -392,7 +392,7 @@ namespace Microsoft.Interop
public IMethodSymbol? FromUnmanaged { get; init; }
public IMethodSymbol? ToUnmanaged { get; init; }
public IMethodSymbol? Free { get; init; }
- public IMethodSymbol? NotifyInvokeSucceeded { get; init; }
+ public IMethodSymbol? OnInvoked { get; init; }
}
public static (MarshallerShape shape, MarshallerMethods methods) GetShapeForType(ITypeSymbol marshallerType, ITypeSymbol managedType, Compilation compilation)
@@ -431,11 +431,11 @@ namespace Microsoft.Interop
}
IMethodSymbol toManaged = GetToManagedMethod(marshallerType, managedType);
- IMethodSymbol toManagedGuaranteed = GetToManagedGuaranteedMethod(marshallerType, managedType);
+ IMethodSymbol toManagedFinally = GetToManagedFinallyMethod(marshallerType, managedType);
IMethodSymbol fromUnmanaged = GetFromUnmanagedMethod(marshallerType, unmanagedType);
- if ((toManaged, toManagedGuaranteed) is not (null, null) && fromUnmanaged is not null)
+ if ((toManaged, toManagedFinally) is not (null, null) && fromUnmanaged is not null)
{
- if (toManagedGuaranteed is not null)
+ if (toManagedFinally is not null)
{
shape |= MarshallerShape.GuaranteedUnmarshal;
}
@@ -447,7 +447,7 @@ namespace Microsoft.Interop
{
FromUnmanaged = fromUnmanaged,
ToManaged = toManaged,
- ToManagedGuranteed = toManagedGuaranteed
+ ToManagedGuranteed = toManagedFinally
};
}
@@ -458,11 +458,11 @@ namespace Microsoft.Interop
methods = methods with { Free = free };
}
- IMethodSymbol notifyInvokeSucceeded = GetNotifyInvokeSucceededMethod(marshallerType);
- if (notifyInvokeSucceeded is not null)
+ IMethodSymbol OnInvoked = GetOnInvokedMethod(marshallerType);
+ if (OnInvoked is not null)
{
- shape |= MarshallerShape.NotifyInvokeSucceeded;
- methods = methods with { NotifyInvokeSucceeded = notifyInvokeSucceeded };
+ shape |= MarshallerShape.OnInvoked;
+ methods = methods with { OnInvoked = OnInvoked };
}
if (GetStatelessGetPinnableReference(marshallerType, managedType) is not null)
@@ -531,9 +531,9 @@ namespace Microsoft.Interop
&& SymbolEqualityComparer.Default.Equals(managedType, m.ReturnType));
}
- private static IMethodSymbol? GetToManagedGuaranteedMethod(ITypeSymbol type, ITypeSymbol managedType)
+ private static IMethodSymbol? GetToManagedFinallyMethod(ITypeSymbol type, ITypeSymbol managedType)
{
- return type.GetMembers(ShapeMemberNames.Value.Stateful.ToManagedGuaranteed)
+ return type.GetMembers(ShapeMemberNames.Value.Stateful.ToManagedFinally)
.OfType()
.FirstOrDefault(m => m is { IsStatic: false, Parameters.Length: 0, ReturnsVoid: false, ReturnsByRef: false, ReturnsByRefReadonly: false }
&& SymbolEqualityComparer.Default.Equals(managedType, m.ReturnType));
@@ -587,9 +587,9 @@ namespace Microsoft.Interop
.FirstOrDefault(m => m is { IsStatic: false, Parameters.Length: 0, ReturnsVoid: true });
}
- private static IMethodSymbol? GetNotifyInvokeSucceededMethod(ITypeSymbol type)
+ private static IMethodSymbol? GetOnInvokedMethod(ITypeSymbol type)
{
- return type.GetMembers(ShapeMemberNames.Value.Stateful.NotifyInvokeSucceeded)
+ return type.GetMembers(ShapeMemberNames.Value.Stateful.OnInvoked)
.OfType()
.FirstOrDefault(m => m is { IsStatic: false, Parameters.Length: 0, ReturnsVoid: true });
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
index 57dc764ba0b..c7117f002f9 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
@@ -13,7 +13,7 @@ using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Microsoft.Interop
{
- public readonly record struct AttributedMarshallingModelOptions(bool RuntimeMarshallingDisabled, Scenario InScenario, Scenario RefScenario, Scenario OutScenario);
+ public readonly record struct AttributedMarshallingModelOptions(bool RuntimeMarshallingDisabled, MarshalMode InMode, MarshalMode RefMode, MarshalMode OutMode);
public class AttributedMarshallingModelGeneratorFactory : IMarshallingGeneratorFactory
{
@@ -214,15 +214,15 @@ namespace Microsoft.Interop
CustomTypeMarshallerData marshallerData;
if (info.IsManagedReturnPosition)
{
- marshallerData = marshalInfo.Marshallers.GetScenarioOrDefault(Options.OutScenario);
+ marshallerData = marshalInfo.Marshallers.GetModeOrDefault(Options.OutMode);
}
else
{
marshallerData = info.RefKind switch
{
- RefKind.None or RefKind.In => marshalInfo.Marshallers.GetScenarioOrDefault(Options.InScenario),
- RefKind.Ref => marshalInfo.Marshallers.GetScenarioOrDefault(Options.RefScenario),
- RefKind.Out => marshalInfo.Marshallers.GetScenarioOrDefault(Options.OutScenario),
+ RefKind.None or RefKind.In => marshalInfo.Marshallers.GetModeOrDefault(Options.InMode),
+ RefKind.Ref => marshalInfo.Marshallers.GetModeOrDefault(Options.RefMode),
+ RefKind.Out => marshalInfo.Marshallers.GetModeOrDefault(Options.OutMode),
_ => throw new MarshallingNotSupportedException(info, context)
};
}
@@ -334,7 +334,7 @@ namespace Microsoft.Interop
{
// Marshalling out or return parameter, but no out marshaller is specified
if ((info.RefKind == RefKind.Out || info.IsManagedReturnPosition)
- && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.OutScenario))
+ && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.OutMode))
{
throw new MarshallingNotSupportedException(info, context)
{
@@ -343,7 +343,7 @@ namespace Microsoft.Interop
}
// Marshalling ref parameter, but no ref marshaller is specified
- if (info.RefKind == RefKind.Ref && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.RefScenario))
+ if (info.RefKind == RefKind.Ref && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.RefMode))
{
throw new MarshallingNotSupportedException(info, context)
{
@@ -353,7 +353,7 @@ namespace Microsoft.Interop
// Marshalling in parameter, but no in marshaller is specified
if (info.RefKind == RefKind.In
- && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.InScenario))
+ && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.InMode))
{
throw new MarshallingNotSupportedException(info, context)
{
@@ -365,7 +365,7 @@ namespace Microsoft.Interop
if (!info.IsByRef
&& !info.IsManagedReturnPosition
&& context.SingleFrameSpansNativeContext
- && !(marshalInfo.IsPinnableManagedType || marshalInfo.Marshallers.IsDefinedOrDefault(Options.InScenario)))
+ && !(marshalInfo.IsPinnableManagedType || marshalInfo.Marshallers.IsDefinedOrDefault(Options.InMode)))
{
throw new MarshallingNotSupportedException(info, context)
{
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
index 048c89867d0..210fc4bf25e 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
@@ -74,7 +74,7 @@ namespace Microsoft.Interop
(string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);
- // = .ConvertToManagedGuaranteed();
+ // = .ConvertToManagedFinally();
yield return ExpressionStatement(
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
@@ -82,7 +82,7 @@ namespace Microsoft.Interop
InvocationExpression(
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
_marshallerTypeSyntax,
- IdentifierName(ShapeMemberNames.Value.Stateless.ConvertToManagedGuaranteed)),
+ IdentifierName(ShapeMemberNames.Value.Stateless.ConvertToManagedFinally)),
ArgumentList(SingletonSeparatedList(
Argument(IdentifierName(nativeIdentifier)))))));
}
@@ -324,7 +324,7 @@ namespace Microsoft.Interop
(string managedIdentifier, _) = context.GetIdentifiers(info);
- // = .ToManagedGuaranteed();
+ // = .ToManagedFinally();
yield return ExpressionStatement(
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
@@ -332,7 +332,7 @@ namespace Microsoft.Interop
InvocationExpression(
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(context.GetAdditionalIdentifier(info, MarshallerIdentifier)),
- IdentifierName(ShapeMemberNames.Value.Stateful.ToManagedGuaranteed)),
+ IdentifierName(ShapeMemberNames.Value.Stateful.ToManagedFinally)),
ArgumentList())));
}
@@ -438,15 +438,15 @@ namespace Microsoft.Interop
public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context)
{
- if (!_shape.HasFlag(MarshallerShape.NotifyInvokeSucceeded))
+ if (!_shape.HasFlag(MarshallerShape.OnInvoked))
yield break;
- // .NotifyInvokeSucceeded();
+ // .OnInvoked();
yield return ExpressionStatement(
InvocationExpression(
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(context.GetAdditionalIdentifier(info, MarshallerIdentifier)),
- IdentifierName(ShapeMemberNames.Value.Stateful.NotifyInvokeSucceeded)),
+ IdentifierName(ShapeMemberNames.Value.Stateful.OnInvoked)),
ArgumentList()));
}
}
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 7269e4f444c..d3987fba7ec 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
@@ -627,7 +627,7 @@ namespace Microsoft.Interop
else if (type is INamedTypeSymbol namedManagedType)
{
// Entry point type for linear collection marshalling must have the arity of the managed type + 1
- // for the [ElementUnmanagedType] placeholder
+ // for the element unmanaged type placeholder
if (entryPointType.Arity != namedManagedType.Arity + 1)
{
_diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerEntryPointTypeMustMatchArity), entryPointType.ToDisplayString(), type.ToDisplayString());
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj
index e3325f0935a..02621feb273 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj
@@ -17,8 +17,8 @@
Link="Production\CustomTypeMarshallerFeatures.cs" />
-
+
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 5428b971559..f0a96eb7c49 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
@@ -18,7 +18,7 @@ namespace Microsoft.Interop
public const string CustomMarshallerAttribute = "System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute";
public const string CustomMarshallerAttributeGenericPlaceholder = CustomMarshallerAttribute + ".GenericPlaceholder";
- public const string ElementUnmanagedTypeAttribute = "System.Runtime.InteropServices.Marshalling.ElementUnmanagedTypeAttribute";
+ public const string ContiguousCollectionMarshallerAttribute = "System.Runtime.InteropServices.Marshalling.ContiguousCollectionMarshallerAttribute";
public const string AnsiStringMarshaller = "System.Runtime.InteropServices.Marshalling.AnsiStringMarshaller";
public const string BStrStringMarshaller = "System.Runtime.InteropServices.Marshalling.BStrStringMarshaller";
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 0a3c15e1955..bbc7222170a 100644
--- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
+++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
@@ -2169,6 +2169,19 @@ namespace System.Runtime.InteropServices.Marshalling
public string? ToManaged() { throw null; }
public void FreeNative() { }
}
+
+ [System.AttributeUsageAttribute(System.AttributeTargets.Struct | System.AttributeTargets.Class, AllowMultiple = true)]
+ public sealed partial class CustomMarshallerAttribute : System.Attribute
+ {
+ public CustomMarshallerAttribute(System.Type managedType, System.Runtime.InteropServices.Marshalling.MarshalMode marshalMode, System.Type marshallerType) { }
+ public System.Type ManagedType { get { throw null; } }
+ public System.Runtime.InteropServices.Marshalling.MarshalMode MarshalMode { get { throw null; } }
+ public System.Type MarshallerType { get { throw null; } }
+ public struct GenericPlaceholder
+ {
+ }
+ }
+
[System.AttributeUsageAttribute(System.AttributeTargets.Struct)]
public sealed partial class CustomTypeMarshallerAttribute : System.Attribute
{
@@ -2204,6 +2217,19 @@ namespace System.Runtime.InteropServices.Marshalling
Value,
LinearCollection
}
+ public enum MarshalMode
+ {
+ Default = 0,
+ ManagedToUnmanagedIn = 1,
+ ManagedToUnmanagedRef = 2,
+ ManagedToUnmanagedOut = 3,
+ UnmanagedToManagedIn = 4,
+ UnmanagedToManagedRef = 5,
+ UnmanagedToManagedOut = 6,
+ ElementIn = 7,
+ ElementRef = 8,
+ ElementOut = 9
+ }
[System.AttributeUsageAttribute(System.AttributeTargets.Parameter | System.AttributeTargets.ReturnValue, AllowMultiple = true)]
public sealed partial class MarshalUsingAttribute : System.Attribute
{
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ContiguousCollectionMarshallerAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ContiguousCollectionMarshallerAttribute.cs
new file mode 100644
index 00000000000..2261b4279d3
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ContiguousCollectionMarshallerAttribute.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.InteropServices.Marshalling
+{
+ ///
+ /// Specifies that this marshaller entry-point type is a contiguous collection marshaller.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
+ public sealed class ContiguousCollectionMarshallerAttribute : Attribute
+ {
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/CustomMarshallerAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/CustomMarshallerAttribute.cs
deleted file mode 100644
index 55abce124ab..00000000000
--- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/CustomMarshallerAttribute.cs
+++ /dev/null
@@ -1,35 +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
-
-using System;
-
-namespace System.Runtime.InteropServices.Marshalling
-{
- ///
- /// Attribute to indicate an entry point type for defining a marshaller.
- ///
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
-#if LIBRARYIMPORT_GENERATOR_TEST
- public
-#else
- internal
-#endif
- sealed class CustomMarshallerAttribute : Attribute
- {
- ///
- /// Create a instance.
- ///
- /// Managed type to marshal.
- /// Marshalling scenario.
- /// Type used for marshalling.
- public CustomMarshallerAttribute(Type managedType, Scenario scenario, Type marshallerType) { }
-
- ///
- /// Placeholder type for generic parameter
- ///
- public struct GenericPlaceholder
- {
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ElementUnmanagedTypeAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ElementUnmanagedTypeAttribute.cs
deleted file mode 100644
index d0f508904a1..00000000000
--- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ElementUnmanagedTypeAttribute.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Runtime.InteropServices.Marshalling
-{
- ///
- /// Specifies that a particular generic parameter is the collection element's unmanaged type.
- ///
- ///
- /// If this attribute is provided on a generic parameter of a marshaller, then the generator will assume
- /// that it is a linear collection marshaller.
- ///
- [AttributeUsage(AttributeTargets.GenericParameter)]
- public sealed class ElementUnmanagedTypeAttribute : Attribute
- {
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs
index c21a7d918f7..5e9a86c4a27 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.cs
@@ -47,19 +47,19 @@ namespace LibraryImportGenerator.IntegrationTests
[return: MarshalUsing(typeof(IntGuaranteedUnmarshal))]
public static partial int GuaranteedUnmarshal([MarshalUsing(typeof(ExceptionOnUnmarshal))] out int ret);
- [CustomMarshaller(typeof(int), Scenario.ManagedToUnmanagedOut, typeof(ExceptionOnUnmarshal))]
+ [CustomMarshaller(typeof(int), MarshalMode.ManagedToUnmanagedOut, typeof(ExceptionOnUnmarshal))]
public static class ExceptionOnUnmarshal
{
public static int ConvertToManaged(int unmanaged) => throw new Exception();
}
- [CustomMarshaller(typeof(int), Scenario.ManagedToUnmanagedOut, typeof(IntGuaranteedUnmarshal))]
+ [CustomMarshaller(typeof(int), MarshalMode.ManagedToUnmanagedOut, typeof(IntGuaranteedUnmarshal))]
public static unsafe class IntGuaranteedUnmarshal
{
- public static bool ConvertToManagedGuaranteedCalled = false;
- public static int ConvertToManagedGuaranteed(int unmanaged)
+ public static bool ConvertToManagedFinallyCalled = false;
+ public static int ConvertToManagedFinally(int unmanaged)
{
- ConvertToManagedGuaranteedCalled = true;
+ ConvertToManagedFinallyCalled = true;
return unmanaged;
}
}
@@ -134,9 +134,9 @@ namespace LibraryImportGenerator.IntegrationTests
[Fact]
public void GuaranteedUnmarshal()
{
- NativeExportsNE.Stateless.IntGuaranteedUnmarshal.ConvertToManagedGuaranteedCalled = false;
+ NativeExportsNE.Stateless.IntGuaranteedUnmarshal.ConvertToManagedFinallyCalled = false;
Assert.Throws(() => NativeExportsNE.Stateless.GuaranteedUnmarshal(out _));
- Assert.True(NativeExportsNE.Stateless.IntGuaranteedUnmarshal.ConvertToManagedGuaranteedCalled);
+ Assert.True(NativeExportsNE.Stateless.IntGuaranteedUnmarshal.ConvertToManagedFinallyCalled);
}
[Fact]
@@ -240,7 +240,7 @@ namespace LibraryImportGenerator.IntegrationTests
}
[Fact]
- public void NotifyInvokeSucceededInNoReturn()
+ public void OnInvokedInNoReturn()
{
bool xNotified = false;
bool yNotified = false;
@@ -260,7 +260,7 @@ namespace LibraryImportGenerator.IntegrationTests
}
[Fact]
- public void NotifyInvokeSucceededInNoOut()
+ public void OnInvokedInNoOut()
{
bool xNotified = false;
bool yNotified = false;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs
index 06e64cb4332..690b14742d8 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs
@@ -690,7 +690,7 @@ public struct S
}}
";
private static string NonStatic = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
public class Marshaller
{
public struct Native { }
@@ -705,7 +705,7 @@ public class Marshaller
public static class Stateless
{
private static string In = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
public static class Marshaller
{
public struct Native { }
@@ -714,7 +714,7 @@ public static class Marshaller
}
";
private static string InBuffer = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
public static class Marshaller
{
public struct Native { }
@@ -725,7 +725,7 @@ public static class Marshaller
";
public static string InPinnable = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
public static unsafe class Marshaller
{
public static byte* ConvertToUnmanaged(S s) => default;
@@ -733,7 +733,7 @@ public static unsafe class Marshaller
}
";
private static string Out = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedOut, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))]
public static class Marshaller
{
public struct Native { }
@@ -742,16 +742,16 @@ public static class Marshaller
}
";
private static string OutGuaranteed = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedOut, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))]
public static class Marshaller
{
public struct Native { }
- public static S ConvertToManagedGuaranteed(Native n) => default;
+ public static S ConvertToManagedFinally(Native n) => default;
}
";
public static string Ref = @"
-[CustomMarshaller(typeof(S), Scenario.Default, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public struct Native { }
@@ -761,8 +761,8 @@ public static class Marshaller
}
";
public static string RefBuffer = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))]
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedOut, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))]
public static class Marshaller
{
public struct Native { }
@@ -773,7 +773,7 @@ public static class Marshaller
}
";
public static string RefOptionalBuffer = @"
-[CustomMarshaller(typeof(S), Scenario.Default, typeof(Marshaller))]
+[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))]
public static class Marshaller
{
public struct Native { }
@@ -793,7 +793,7 @@ public static class Marshaller
+ NonBlittableUserDefinedType()
+ Out;
- public static string NativeToManagedGuaranteedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S")
+ public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S")
+ NonBlittableUserDefinedType()
+ OutGuaranteed;
@@ -805,7 +805,7 @@ public static class Marshaller
+ NonBlittableUserDefinedType()
+ Out;
- public static string NativeToManagedGuaranteedOnlyReturnValue => BasicReturnType("S")
+ public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S")
+ NonBlittableUserDefinedType()
+ Out;
@@ -844,7 +844,7 @@ public static class Marshaller
public static class Stateful
{
private static string In = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -858,7 +858,7 @@ public static class Marshaller
";
public static string InStatelessPinnable = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))]
public static class Marshaller
{
public unsafe struct M
@@ -872,7 +872,7 @@ public static class Marshaller
";
public static string InPinnable = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))]
public static class Marshaller
{
public unsafe struct M
@@ -886,7 +886,7 @@ public static class Marshaller
";
private static string InBuffer = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -900,7 +900,7 @@ public static class Marshaller
}
";
private static string Out = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedOut, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -913,7 +913,7 @@ public static class Marshaller
}
";
private static string OutGuaranteed = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedOut, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -921,12 +921,12 @@ public static class Marshaller
public struct M
{
public void FromUnmanaged(Native n) {}
- public S ToManagedGuaranteed() => default;
+ public S ToManagedFinally() => default;
}
}
";
public static string Ref = @"
-[CustomMarshaller(typeof(S), Scenario.Default, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -941,7 +941,7 @@ public static class Marshaller
}
";
public static string RefWithFree = @"
-[CustomMarshaller(typeof(S), Scenario.Default, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -956,8 +956,8 @@ public static class Marshaller
}
}
";
- public static string RefWithNotifyInvokeSucceeded = @"
-[CustomMarshaller(typeof(S), Scenario.Default, typeof(M))]
+ public static string RefWithOnInvoked = @"
+[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -968,13 +968,13 @@ public static class Marshaller
public Native ToUnmanaged() => default;
public void FromUnmanaged(Native n) {}
public S ToManaged() => default;
- public void NotifyInvokeSucceeded() {}
+ public void OnInvoked() {}
}
}
";
public static string RefBuffer = @"
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedIn, typeof(M))]
-[CustomMarshaller(typeof(S), Scenario.ManagedToUnmanagedOut, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -990,7 +990,7 @@ public static class Marshaller
}
";
public static string RefOptionalBuffer = @"
-[CustomMarshaller(typeof(S), Scenario.Default, typeof(M))]
+[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))]
public static class Marshaller
{
public struct Native { }
@@ -1015,7 +1015,7 @@ public static class Marshaller
+ NonBlittableUserDefinedType()
+ Out;
- public static string NativeToManagedGuaranteedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S")
+ public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S")
+ NonBlittableUserDefinedType()
+ OutGuaranteed;
@@ -1027,7 +1027,7 @@ public static class Marshaller
+ NonBlittableUserDefinedType()
+ Out;
- public static string NativeToManagedGuaranteedOnlyReturnValue => BasicReturnType("S")
+ public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S")
+ NonBlittableUserDefinedType()
+ Out;
@@ -1043,9 +1043,9 @@ public static class Marshaller
+ NonBlittableUserDefinedType(defineNativeMarshalling: true)
+ RefWithFree;
- public static string ParametersAndModifiersWithNotifyInvokeSucceeded = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling)
+ public static string ParametersAndModifiersWithOnInvoked = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling)
+ NonBlittableUserDefinedType(defineNativeMarshalling: true)
- + RefWithNotifyInvokeSucceeded;
+ + RefWithOnInvoked;
public static string MarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Marshaller")
+ NonBlittableUserDefinedType(defineNativeMarshalling: false)
@@ -1457,8 +1457,9 @@ partial class Test
public static class Stateless
{
public const string In = @"
-[CustomMarshaller(typeof(TestCollection<>), Scenario.ManagedToUnmanagedIn, typeof(Marshaller<,>))]
-static unsafe class Marshaller
+[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))]
+[ContiguousCollectionMarshaller]
+static unsafe class Marshaller
{
public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null;
public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null;
@@ -1466,8 +1467,9 @@ static unsafe class Marshaller
}
";
public const string InPinnable = @"
-[CustomMarshaller(typeof(TestCollection<>), Scenario.ManagedToUnmanagedIn, typeof(Marshaller<,>))]
-static unsafe class Marshaller
+[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))]
+[ContiguousCollectionMarshaller]
+static unsafe class Marshaller
{
public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null;
public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null;
@@ -1477,8 +1479,9 @@ static unsafe class Marshaller
}
";
public const string InBuffer = @"
-[CustomMarshaller(typeof(TestCollection<>), Scenario.ManagedToUnmanagedIn, typeof(Marshaller<,>))]
-static unsafe class Marshaller
+[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))]
+[ContiguousCollectionMarshaller]
+static unsafe class Marshaller
{
public const int BufferSize = 0x100;
public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, System.Span buffer, out int numElements) => throw null;
@@ -1487,8 +1490,9 @@ static unsafe class Marshaller
}
";
public const string Ref = @"
-[CustomMarshaller(typeof(TestCollection<>), Scenario.Default, typeof(Marshaller<,>))]
-static unsafe class Marshaller
+[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>))]
+[ContiguousCollectionMarshaller]
+static unsafe class Marshaller
{
public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null;
public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null;
@@ -1500,8 +1504,9 @@ static unsafe class Marshaller
}
";
public const string RefNested = @"
-[CustomMarshaller(typeof(TestCollection<>), Scenario.Default, typeof(Marshaller<,>.Ref.Nested))]
-static unsafe class Marshaller
+[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Ref.Nested))]
+[ContiguousCollectionMarshaller]
+static unsafe class Marshaller
{
static class Nested
{
@@ -1519,8 +1524,9 @@ static unsafe class Marshaller
}
";
public const string Out = @"
-[CustomMarshaller(typeof(TestCollection<>), Scenario.ManagedToUnmanagedOut, typeof(Marshaller<,>))]
-static unsafe class Marshaller
+[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller<,>))]
+[ContiguousCollectionMarshaller]
+static unsafe class Marshaller
{
public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null;
public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null;
@@ -1577,8 +1583,9 @@ static unsafe class Marshaller
[NativeMarshalling(typeof(Marshaller<,,>))]
class TestCollection {}
-[CustomMarshaller(typeof(TestCollection<>), Scenario.Default, typeof(Marshaller<,,>))]
-static unsafe class Marshaller
+[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,,>))]
+[ContiguousCollectionMarshaller]
+static unsafe class Marshaller
{
public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null;
public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs
index 21ebc41f7ea..2c78a8d2d57 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs
@@ -173,21 +173,21 @@ namespace LibraryImportGenerator.UnitTests
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.ParametersAndModifiers };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.MarshalUsingParametersAndModifiers };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyOutParameter };
- yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedGuaranteedOnlyOutParameter };
+ yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyOutParameter };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyReturnValue };
- yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedGuaranteedOnlyReturnValue };
+ yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyReturnValue };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.PinByValueInParameter };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.StackallocByValueInParameter };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.StackallocParametersAndModifiersNoRef };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateless.OptionalStackallocParametersAndModifiers };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiers };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithFree };
- yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithNotifyInvokeSucceeded };
+ yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithOnInvoked };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.MarshalUsingParametersAndModifiers };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyOutParameter };
- yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedGuaranteedOnlyOutParameter };
+ yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyOutParameter };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyReturnValue };
- yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedGuaranteedOnlyReturnValue };
+ yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyReturnValue };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.StackallocByValueInParameter };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.PinByValueInParameter };
yield return new[] { CodeSnippets.CustomStructMarshalling.Stateful.MarshallerPinByValueInParameter };
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.cs
index 62065e639a7..85795088934 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.cs
@@ -20,9 +20,9 @@ namespace SharedTypes
public string str2;
}
- [CustomMarshaller(typeof(StringContainer), Scenario.ManagedToUnmanagedIn, typeof(In))]
- [CustomMarshaller(typeof(StringContainer), Scenario.ManagedToUnmanagedRef, typeof(Ref))]
- [CustomMarshaller(typeof(StringContainer), Scenario.ManagedToUnmanagedOut, typeof(Out))]
+ [CustomMarshaller(typeof(StringContainer), MarshalMode.ManagedToUnmanagedIn, typeof(In))]
+ [CustomMarshaller(typeof(StringContainer), MarshalMode.ManagedToUnmanagedRef, typeof(Ref))]
+ [CustomMarshaller(typeof(StringContainer), MarshalMode.ManagedToUnmanagedOut, typeof(Out))]
public static class StringContainerMarshaller
{
public struct StringContainerNative
@@ -77,7 +77,7 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(double), Scenario.ManagedToUnmanagedIn, typeof(DoubleToBytesBigEndianMarshaller))]
+ [CustomMarshaller(typeof(double), MarshalMode.ManagedToUnmanagedIn, typeof(DoubleToBytesBigEndianMarshaller))]
public static unsafe class DoubleToBytesBigEndianMarshaller
{
public const int BufferSize = 8;
@@ -89,7 +89,7 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(double), Scenario.ManagedToUnmanagedIn, typeof(DoubleToLongMarshaller))]
+ [CustomMarshaller(typeof(double), MarshalMode.ManagedToUnmanagedIn, typeof(DoubleToLongMarshaller))]
public static class DoubleToLongMarshaller
{
public static long ConvertToUnmanaged(double managed)
@@ -106,7 +106,7 @@ namespace SharedTypes
public bool b3;
}
- [CustomMarshaller(typeof(BoolStruct), Scenario.Default, typeof(BoolStructMarshaller))]
+ [CustomMarshaller(typeof(BoolStruct), MarshalMode.Default, typeof(BoolStructMarshaller))]
public static class BoolStructMarshaller
{
public struct BoolStructNative
@@ -145,7 +145,7 @@ namespace SharedTypes
public ref int GetPinnableReference() => ref i;
}
- [CustomMarshaller(typeof(IntWrapper), Scenario.Default, typeof(IntWrapperMarshaller))]
+ [CustomMarshaller(typeof(IntWrapper), MarshalMode.Default, typeof(IntWrapperMarshaller))]
public static unsafe class IntWrapperMarshaller
{
public static int* ConvertToUnmanaged(IntWrapper managed)
@@ -166,7 +166,7 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(IntWrapper), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(IntWrapper), MarshalMode.Default, typeof(Marshaller))]
public static unsafe class IntWrapperMarshallerStateful
{
public struct Marshaller
@@ -205,7 +205,7 @@ namespace SharedTypes
public int i;
}
- [CustomMarshaller(typeof(IntWrapperWithoutGetPinnableReference), Scenario.Default, typeof(IntWrapperWithoutGetPinnableReferenceMarshaller))]
+ [CustomMarshaller(typeof(IntWrapperWithoutGetPinnableReference), MarshalMode.Default, typeof(IntWrapperWithoutGetPinnableReferenceMarshaller))]
public static unsafe class IntWrapperWithoutGetPinnableReferenceMarshaller
{
public static int* ConvertToUnmanaged(IntWrapperWithoutGetPinnableReference managed)
@@ -228,7 +228,7 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(IntWrapperWithoutGetPinnableReference), Scenario.ManagedToUnmanagedIn, typeof(StatelessGetPinnableReference))]
+ [CustomMarshaller(typeof(IntWrapperWithoutGetPinnableReference), MarshalMode.ManagedToUnmanagedIn, typeof(StatelessGetPinnableReference))]
public static unsafe class IntWrapperWithoutGetPinnableReferenceStatefulMarshaller
{
public struct StatelessGetPinnableReference
@@ -242,7 +242,7 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(IntWrapperWithoutGetPinnableReference), Scenario.ManagedToUnmanagedIn, typeof(StatefulGetPinnableReference))]
+ [CustomMarshaller(typeof(IntWrapperWithoutGetPinnableReference), MarshalMode.ManagedToUnmanagedIn, typeof(StatefulGetPinnableReference))]
public static unsafe class IntWrapperWithoutGetPinnableReferenceStatefulNoAllocMarshaller
{
public struct StatefulGetPinnableReference
@@ -281,7 +281,7 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(IntWrapperWithNotification), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(IntWrapperWithNotification), MarshalMode.Default, typeof(Marshaller))]
public static class IntWrapperWithNotificationMarshaller
{
public struct Marshaller
@@ -296,11 +296,11 @@ namespace SharedTypes
public IntWrapperWithNotification ToManaged() => _managed;
- public void NotifyInvokeSucceeded() => _managed.RaiseInvokeSucceeded();
+ public void OnInvoked() => _managed.RaiseInvokeSucceeded();
}
}
- [CustomMarshaller(typeof(BoolStruct), Scenario.Default, typeof(Marshaller))]
+ [CustomMarshaller(typeof(BoolStruct), MarshalMode.Default, typeof(Marshaller))]
public static class BoolStructMarshallerStateful
{
public struct BoolStructNative
@@ -339,8 +339,9 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(List<>), Scenario.Default, typeof(ListMarshaller<,>))]
- public unsafe static class ListMarshaller where TUnmanagedElement : unmanaged
+ [CustomMarshaller(typeof(List<>), MarshalMode.Default, typeof(ListMarshaller<,>))]
+ [ContiguousCollectionMarshaller]
+ public unsafe static class ListMarshaller where TUnmanagedElement : unmanaged
{
public static byte* AllocateContainerForUnmanagedElements(List managed, out int numElements)
=> AllocateContainerForUnmanagedElements(managed, Span.Empty, out numElements);
@@ -397,8 +398,9 @@ namespace SharedTypes
=> Marshal.FreeCoTaskMem((IntPtr)unmanaged);
}
- [CustomMarshaller(typeof(List<>), Scenario.Default, typeof(ListMarshallerWithPinning<,>))]
- public unsafe static class ListMarshallerWithPinning where TUnmanagedElement : unmanaged
+ [CustomMarshaller(typeof(List<>), MarshalMode.Default, typeof(ListMarshallerWithPinning<,>))]
+ [ContiguousCollectionMarshaller]
+ public unsafe static class ListMarshallerWithPinning where TUnmanagedElement : unmanaged
{
public static byte* AllocateContainerForUnmanagedElements(List managed, out int numElements)
=> AllocateContainerForUnmanagedElements(managed, Span.Empty, out numElements);
@@ -464,8 +466,9 @@ namespace SharedTypes
}
}
- [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), Scenario.Default, typeof(CustomArrayMarshaller<,>))]
- public unsafe static class CustomArrayMarshaller where TUnmanagedElement : unmanaged
+ [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.Default, typeof(CustomArrayMarshaller<,>))]
+ [ContiguousCollectionMarshaller]
+ public unsafe static class CustomArrayMarshaller where TUnmanagedElement : unmanaged
{
public static byte* AllocateContainerForUnmanagedElements(T[]? managed, out int numElements)
{