diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs index c47349485..c2b009cea 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs @@ -8,6 +8,7 @@ using AsmResolver.PE.DotNet.Cil; using AsmResolver.PE.DotNet.Metadata.Tables; using WindowsRuntime.InteropGenerator.Factories; +using WindowsRuntime.InteropGenerator.Generation; using WindowsRuntime.InteropGenerator.References; using static AsmResolver.PE.DotNet.Cil.CilOpCodes; @@ -26,121 +27,129 @@ public static class SzArray /// /// The for the SZ array type. /// The instance to use. + /// The emit state for this invocation. /// The module that will contain the type being created. /// The resulting marshaller type. public static void Marshaller( SzArrayTypeSignature arrayType, InteropReferences interopReferences, + InteropGeneratorEmitState emitState, ModuleDefinition module, out TypeDefinition marshallerType) { TypeSignature elementType = arrayType.BaseType; - TypeSignature elementAbiType = elementType.GetAbiType(interopReferences); - // We're declaring an 'internal static class' type - marshallerType = new( - ns: InteropUtf8NameFactory.TypeNamespace(arrayType), - name: InteropUtf8NameFactory.TypeName(arrayType, "Marshaller"), - attributes: TypeAttributes.AutoLayout | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit, - baseType: module.CorLibTypeFactory.Object.ToTypeDefOrRef()); - - module.TopLevelTypes.Add(marshallerType); - - // Define the 'ConvertToUnmanaged' method as follows: - // - // public static void ConvertToUnmanaged(ReadOnlySpan<>, out uint size, out * array) - MethodDefinition convertToUnmanagedMethod = new( - name: "ConvertToUnmanaged"u8, - attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, - signature: MethodSignature.CreateStatic( - returnType: module.CorLibTypeFactory.Void, - parameterTypes: [ - interopReferences.ReadOnlySpan1.MakeGenericValueType(elementType).Import(module), - module.CorLibTypeFactory.UInt32.MakeByReferenceType(), - elementAbiType.Import(module).MakePointerType().MakeByReferenceType()])) + // Emit the right marshaller based on the element type. We special case all different + // kinds of element types because some need specialized marshallers, and some need + // a generated element marshaller type. The marshaller itself just forwards all calls. + if (elementType.IsBlittable(interopReferences)) { - CilOutParameterIndices = [2, 3], - CilInstructions = - { - { Ldnull }, - { Throw } // TODO - } - }; - - marshallerType.Methods.Add(convertToUnmanagedMethod); - - // Define the 'ConvertToManaged' method as follows: - // - // public static [] ConvertToManaged(uint size, * value) - MethodDefinition convertToManagedMethod = new( - name: "ConvertToManaged"u8, - attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, - signature: MethodSignature.CreateStatic( - returnType: arrayType.Import(module), - parameterTypes: [ - module.CorLibTypeFactory.UInt32, - elementAbiType.Import(module).MakePointerType()])) + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.BlittableValueType( + arrayType: arrayType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } + else if (elementType.IsConstructedKeyValuePairType(interopReferences)) { - CilInstructions = - { - { Ldnull }, - { Throw } // TODO - } - }; - - marshallerType.Methods.Add(convertToManagedMethod); - - // Define the 'CopyToManaged' method as follows: - // - // public static void CopyToManaged(uint size, * value, Span<> destination) - MethodDefinition copyToManagedMethod = new( - name: "CopyToManaged"u8, - attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, - signature: MethodSignature.CreateStatic( - returnType: module.CorLibTypeFactory.Void, - parameterTypes: [ - module.CorLibTypeFactory.UInt32, - elementAbiType.Import(module).MakePointerType(), - interopReferences.Span1.MakeGenericValueType(elementType).Import(module)])) + TypeDefinition elementMarshallerType = InteropTypeDefinitionFactory.SzArrayElementMarshaller.KeyValuePair( + arrayType: arrayType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + + module.TopLevelTypes.Add(elementMarshallerType); + + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.KeyValuePair( + arrayType: arrayType, + elementMarshallerType: elementMarshallerType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } + else if (elementType.IsManagedValueType(interopReferences)) { - CilInstructions = - { - { Ldnull }, - { Throw } // TODO - } - }; - - marshallerType.Methods.Add(copyToManagedMethod); - - // Define the 'CopyToUnmanaged' method as follows: - // - // public static void CopyToUnmanaged(ReadOnlySpan<> value, uint size, * destination) - MethodDefinition copyToUnmanagedMethod = new( - name: "CopyToUnmanaged"u8, - attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, - signature: MethodSignature.CreateStatic( - returnType: module.CorLibTypeFactory.Void, - parameterTypes: [ - interopReferences.ReadOnlySpan1.MakeGenericValueType(elementType).Import(module), - module.CorLibTypeFactory.UInt32, - elementAbiType.Import(module).MakePointerType()])) + TypeDefinition elementMarshallerType = InteropTypeDefinitionFactory.SzArrayElementMarshaller.ManagedValueType( + arrayType: arrayType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + + module.TopLevelTypes.Add(elementMarshallerType); + + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.ManagedValueType( + arrayType: arrayType, + elementMarshallerType: elementMarshallerType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } + else if (elementType.IsValueType) { - CilInstructions = - { - { Ldnull }, - { Throw } // TODO - } - }; - - marshallerType.Methods.Add(copyToUnmanagedMethod); - - // Define the 'Free' method - MethodDefinition freeMethod = InteropMethodDefinitionFactory.SzArrayMarshaller.Free( - arrayType, - interopReferences, - module); - - marshallerType.Methods.Add(freeMethod); + TypeDefinition elementMarshallerType = InteropTypeDefinitionFactory.SzArrayElementMarshaller.UnmanagedValueType( + arrayType: arrayType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + + module.TopLevelTypes.Add(elementMarshallerType); + + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.UnmanagedValueType( + arrayType: arrayType, + elementMarshallerType: elementMarshallerType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } + else if (elementType.IsTypeOfString()) + { + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.String( + arrayType: arrayType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } + else if (elementType.IsTypeOfType(interopReferences)) + { + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.Type( + arrayType: arrayType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } + else if (elementType.IsTypeOfException(interopReferences)) + { + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.Exception( + arrayType: arrayType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } + else + { + TypeDefinition elementMarshallerType = InteropTypeDefinitionFactory.SzArrayElementMarshaller.ReferenceType( + arrayType: arrayType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + + module.TopLevelTypes.Add(elementMarshallerType); + + marshallerType = InteropTypeDefinitionFactory.SzArrayMarshaller.ReferenceType( + arrayType: arrayType, + elementMarshallerType: elementMarshallerType, + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(marshallerType); + } } /// diff --git a/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs b/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs index b7a32c0d8..d3f52d08d 100644 --- a/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs +++ b/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs @@ -597,6 +597,14 @@ public static WellKnownInteropException MethodRewriteSourceParameterTypeMismatch return Exception(69, $"Parameter variable of type '{parameterType}' cannot be used to marshal a value of type '{returnType}' in generated interop method '{method}'."); } + /// + /// A type doesn't have the Dispose method available. + /// + public static WellKnownInteropException MethodRewriteDisposeNotAvailableError(TypeSignature parameterType, MethodDefinition method) + { + return Exception(70, $"Value of type '{parameterType}' in generated interop method '{method}' cannot be disposed, as it is an unmanaged (or blittable) value type."); + } + /// /// Creates a new exception with the specified id and message. /// diff --git a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs index 3a7805e0e..a9b14fe0e 100644 --- a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs +++ b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs @@ -583,6 +583,22 @@ public TypeSignature GetAbiType(InteropReferences interopReferences) // For all other cases (e.g. interfaces, classes, delegates, etc.), the ABI type is always a pointer return interopReferences.CorLibTypeFactory.Void.MakePointerType(); } + + /// + /// Gets the raw ABI type for a given type (without unwrapping). + /// + /// The instance to use. + /// The raw ABI type for the input type. + public TypeSignature GetRawAbiType(InteropReferences interopReferences) + { + TypeSignature abiType = type.GetAbiType(interopReferences); + + // If the ABI type is 'void*', the marshaller types return it as 'WindowsRuntimeObjectReferenceValue'. + // This allows callers to do proper lifetime management. For all other cases, the ABI type is the same. + return abiType.IsTypeOfVoidPointer() + ? interopReferences.WindowsRuntimeObjectReferenceValue.ToValueTypeSignature() + : abiType; + } } extension(TypeDefinition type) diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IEnumerator1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IEnumerator1Impl.cs index c1ddf2a59..b2234b61c 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IEnumerator1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IEnumerator1Impl.cs @@ -15,10 +15,8 @@ namespace WindowsRuntime.InteropGenerator.Factories; -/// -/// A factory for interop method definitions. -/// -internal static partial class InteropMethodDefinitionFactory +/// +internal partial class InteropMethodDefinitionFactory { /// /// Helpers for impl types for interfaces. diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IList1Impl.cs index fc7ee5629..de4097bc8 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IList1Impl.cs @@ -15,10 +15,8 @@ namespace WindowsRuntime.InteropGenerator.Factories; -/// -/// A factory for interop method definitions. -/// -internal static partial class InteropMethodDefinitionFactory +/// +internal partial class InteropMethodDefinitionFactory { /// /// Helpers for impl types for interfaces. diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.cs index 1a71cc127..3e20eee50 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.cs @@ -14,10 +14,8 @@ namespace WindowsRuntime.InteropGenerator.Factories; -/// -/// A factory for interop method definitions. -/// -internal static partial class InteropMethodDefinitionFactory +/// +internal partial class InteropMethodDefinitionFactory { /// /// Helpers for impl types for interfaces. diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs index a70f3fcd9..2133d8990 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -14,10 +14,8 @@ namespace WindowsRuntime.InteropGenerator.Factories; -/// -/// A factory for interop method definitions. -/// -internal static partial class InteropMethodDefinitionFactory +/// +internal partial class InteropMethodDefinitionFactory { /// /// Helpers for impl types for interfaces. diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.SzArrayMarshaller.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.SzArrayMarshaller.cs deleted file mode 100644 index a41eb897a..000000000 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.SzArrayMarshaller.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using AsmResolver.DotNet; -using AsmResolver.DotNet.Code.Cil; -using AsmResolver.DotNet.Signatures; -using AsmResolver.PE.DotNet.Metadata.Tables; -using WindowsRuntime.InteropGenerator.References; -using static AsmResolver.PE.DotNet.Cil.CilOpCodes; - -namespace WindowsRuntime.InteropGenerator.Factories; - -/// -internal partial class InteropMethodDefinitionFactory -{ - /// - /// Helpers for marshaller types for SZ array types. - /// - public static class SzArrayMarshaller - { - /// - /// Creates a for the Free marshaller method. - /// - /// The for the SZ array type. - /// The instance to use. - /// The module that will contain the type being created. - public static MethodDefinition Free( - SzArrayTypeSignature arrayType, - InteropReferences interopReferences, - ModuleDefinition module) - { - TypeSignature elementType = arrayType.BaseType; - - // Define the 'Free' method as follows: - // - // public static void Free(uint size, * destination) - MethodDefinition freeMethod = new( - name: "Free"u8, - attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, - signature: MethodSignature.CreateStatic( - returnType: module.CorLibTypeFactory.Void, - parameterTypes: [ - module.CorLibTypeFactory.UInt32, - elementType.GetAbiType(interopReferences).Import(module).MakePointerType()])); - - // For 'string', 'Type', reference types and blittable types, we can reuse the shared stubs from the 'WindowsRuntimeArrayHelpers' - // type in WinRT.Runtime.dll, to simplify the code and reduce binary size (as we can reuse all these stubs for multiple types). - if (SignatureComparer.IgnoreVersion.Equals(elementType, interopReferences.CorLibTypeFactory.String)) - { - freeMethod.CilMethodBody = new CilMethodBody - { - Instructions = - { - { Ldarg_0 }, - { Ldarg_1 }, - { Call, interopReferences.WindowsRuntimeArrayHelpersFreeHStringArrayUnsafe.Import(module) }, - { Ret } - } - }; - } - else if (SignatureComparer.IgnoreVersion.Equals(elementType, interopReferences.Type)) - { - freeMethod.CilMethodBody = new CilMethodBody - { - Instructions = - { - { Ldarg_0 }, - { Ldarg_1 }, - { Call, interopReferences.WindowsRuntimeArrayHelpersFreeTypeArrayUnsafe.Import(module) }, - { Ret } - } - }; - } - else if (!elementType.Resolve()!.IsValueType || elementType.IsConstructedKeyValuePairType(interopReferences)) - { - freeMethod.CilMethodBody = new CilMethodBody - { - Instructions = - { - { Ldarg_0 }, - { Ldarg_1 }, - { Call, interopReferences.WindowsRuntimeArrayHelpersFreeObjectArrayUnsafe.Import(module) }, - { Ret } - } - }; - } - else if (elementType.Resolve()!.IsByRefLike) // TODO: check for blittable - { - freeMethod.CilMethodBody = new CilMethodBody - { - Instructions = - { - { Ldarg_0 }, - { Ldarg_1 }, - { Call, interopReferences.WindowsRuntimeArrayHelpersFreeBlittableArrayUnsafe.Import(module) }, - { Ret } - } - }; - } - - return freeMethod; - } - } -} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.Dispose.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.Dispose.cs new file mode 100644 index 000000000..09b2397e0 --- /dev/null +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.Dispose.cs @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; +using WindowsRuntime.InteropGenerator.Errors; +using WindowsRuntime.InteropGenerator.Generation; +using WindowsRuntime.InteropGenerator.References; +using WindowsRuntime.InteropGenerator.Resolvers; +using static AsmResolver.PE.DotNet.Cil.CilOpCodes; + +namespace WindowsRuntime.InteropGenerator.Factories; + +/// +internal partial class InteropMethodRewriteFactory +{ + /// + /// Contains the logic for disposing (or releasing) a given value (already on the stack). + /// + public static class Dispose + { + /// + /// Performs two-pass code generation on a target method to dispose (or release) a given value. + /// + /// The parameter type that needs to be marshalled. + /// The target method to perform two-pass code generation on. + /// The target IL instruction to replace with the right set of specialized instructions. + /// The instance to use. + /// The emit state for this invocation. + /// The interop module being built. + public static void RewriteMethod( + TypeSignature parameterType, + MethodDefinition method, + CilInstruction marker, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + // Validate that we do have some IL body for the input method (this should always be the case) + if (method.CilMethodBody is not CilMethodBody body) + { + throw WellKnownInteropExceptions.MethodRewriteMissingBodyError(method); + } + + // If we didn't find the marker, it means the target method is either invalid + if (!body.Instructions.ReferenceContains(marker)) + { + throw WellKnownInteropExceptions.MethodRewriteMarkerInstructionNotFoundError(marker, method); + } + + // For unmanaged (or blittable) value types, this call is not valid, as they can't be disposed. + // We also need to check whether the type is 'Exception', as its ABI type is blittable as well. + if ((parameterType.IsValueType && !parameterType.IsManagedValueType(interopReferences)) || parameterType.IsTypeOfException(interopReferences)) + { + throw WellKnownInteropExceptions.MethodRewriteDisposeNotAvailableError(parameterType, method); + } + + // For managed value types, we call 'Dispose' on their marshaller type + if (parameterType.IsManagedValueType(interopReferences)) + { + InteropMarshallerType marshallerType = InteropMarshallerTypeResolver.GetMarshallerType(parameterType, interopReferences, emitState); + + body.Instructions.ReferenceReplaceRange(marker, new CilInstruction(Call, marshallerType.Dispose().Import(module))); + } + else if (parameterType.IsTypeOfString()) + { + // When disposing 'string' values, we must use 'HStringMarshaller' (the ABI type is not actually a COM object) + body.Instructions.ReferenceReplaceRange(marker, new CilInstruction(Call, interopReferences.HStringMarshallerFree.Import(module))); + } + else + { + // For everything else, we just release the native object. This also applies to generic value types, + // such as 'KeyValuePair', because they are actually interface types at the ABI level. + body.Instructions.ReferenceReplaceRange(marker, new CilInstruction(Call, interopReferences.WindowsRuntimeUnknownMarshallerFree.Import(module))); + } + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedValue.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedValue.cs index d4d0fe9b1..881c7e1fc 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedValue.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedValue.cs @@ -54,9 +54,11 @@ public static void RewriteMethod( if (parameterType.IsValueType) { - // If the return type is blittable, we have nothing else to do (the value is already loaded) + // If the parameter type is blittable, we have nothing else to do (the value is already loaded) if (parameterType.IsBlittable(interopReferences)) { + _ = body.Instructions.ReferenceRemove(marker); + return; } diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.RawRetVal.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.RawRetVal.cs new file mode 100644 index 000000000..cfad78c8c --- /dev/null +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.RawRetVal.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; +using WindowsRuntime.InteropGenerator.Errors; +using WindowsRuntime.InteropGenerator.Generation; +using WindowsRuntime.InteropGenerator.References; +using WindowsRuntime.InteropGenerator.Resolvers; +using static AsmResolver.PE.DotNet.Cil.CilOpCodes; + +namespace WindowsRuntime.InteropGenerator.Factories; + +/// +internal partial class InteropMethodRewriteFactory +{ + /// + /// Contains the logic for emitting direct calls to ConvertToUnmanaged for a given value (already on the stack). + /// + /// + /// This is similar to , but without protected regions or any unwrapping. + /// + public static class RawRetVal + { + /// + /// Performs two-pass code generation on a target method to emit a direct call to ConvertToUnmanaged. + /// + /// The parameter type that needs to be marshalled. + /// The target method to perform two-pass code generation on. + /// The target IL instruction to replace with the right set of specialized instructions. + /// The instance to use. + /// The emit state for this invocation. + /// The interop module being built. + public static void RewriteMethod( + TypeSignature parameterType, + MethodDefinition method, + CilInstruction marker, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + // Validate that we do have some IL body for the input method (this should always be the case) + // Validate that we do have some IL body for the input method (this should always be thevv case) + if (method.CilMethodBody is not CilMethodBody body) + { + throw WellKnownInteropExceptions.MethodRewriteMissingBodyError(method); + } + + // If we didn't find the marker, it means the target method is either invalid + if (!body.Instructions.ReferenceContains(marker)) + { + throw WellKnownInteropExceptions.MethodRewriteMarkerInstructionNotFoundError(marker, method); + } + + // If the parameter type is blittable, we have nothing else to do (the value is already loaded) + if (parameterType.IsBlittable(interopReferences)) + { + _ = body.Instructions.ReferenceRemove(marker); + + return; + } + + // For nullable values, we actually need to call 'BoxToUnmanaged' + if (parameterType.IsConstructedNullableValueType(interopReferences)) + { + InteropMarshallerType marshallerType = InteropMarshallerTypeResolver.GetMarshallerType(parameterType, interopReferences, emitState); + + body.Instructions.ReferenceReplaceRange(marker, new CilInstruction(Call, marshallerType.BoxToUnmanaged().Import(module))); + } + else + { + // For any other types, we always just forward directly to 'ConvertToUnmanaged', without any other changes + InteropMarshallerType marshallerType = InteropMarshallerTypeResolver.GetMarshallerType(parameterType, interopReferences, emitState); + + body.Instructions.ReferenceReplaceRange(marker, new CilInstruction(Call, marshallerType.ConvertToUnmanaged().Import(module))); + } + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Factories/InteropTypeDefinitionFactory.SzArrayElementMarshaller.cs b/src/WinRT.Interop.Generator/Factories/InteropTypeDefinitionFactory.SzArrayElementMarshaller.cs new file mode 100644 index 000000000..75ee7c6a7 --- /dev/null +++ b/src/WinRT.Interop.Generator/Factories/InteropTypeDefinitionFactory.SzArrayElementMarshaller.cs @@ -0,0 +1,299 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; +using AsmResolver.PE.DotNet.Metadata.Tables; +using WindowsRuntime.InteropGenerator.Generation; +using WindowsRuntime.InteropGenerator.References; +using static AsmResolver.PE.DotNet.Cil.CilOpCodes; + +namespace WindowsRuntime.InteropGenerator.Factories; + +/// +/// A factory for interop type definitions. +/// +internal partial class InteropTypeDefinitionFactory +{ + /// + /// Helpers for element marshaller types for SZ array types. + /// + public static class SzArrayElementMarshaller + { + /// + /// Creates a for the element marshaller for an unmanaged value type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The emit state for this invocation. + /// The module that will contain the type being created. + /// The resulting element marshaller type. + public static TypeDefinition UnmanagedValueType( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + TypeSignature elementAbiType = elementType.GetAbiType(interopReferences); + + // Get the constructed 'IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller' interface type + TypeSignature interfaceType = interopReferences + .IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller2 + .MakeGenericReferenceType(elementType, elementAbiType); + + return ElementMarshaller( + arrayType: arrayType, + interfaceType: interfaceType, + convertToUnmanagedInterfaceMethod: interopReferences.IWindowsRuntimeUnmanagedValueTypeArrayElementMarshallerConvertToUnmanaged(elementType, elementAbiType), + convertToManagedInterfaceMethod: interopReferences.IWindowsRuntimeUnmanagedValueTypeArrayElementMarshallerConvertToManaged(elementType, elementAbiType), + isValueType: true, + interopReferences: interopReferences, + emitState: emitState, + module: module); + } + + /// + /// Creates a for the element marshaller for a managed value type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The emit state for this invocation. + /// The module that will contain the type being created. + /// The resulting element marshaller type. + public static TypeDefinition ManagedValueType( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + TypeSignature elementAbiType = elementType.GetAbiType(interopReferences); + + // Get the constructed 'IWindowsRuntimeManagedValueTypeArrayElementMarshaller' interface type + TypeSignature interfaceType = interopReferences + .IWindowsRuntimeManagedValueTypeArrayElementMarshaller2 + .MakeGenericReferenceType(elementType, elementAbiType); + + // Get the element marshaller type with the common method implementations + TypeDefinition elementMarshallerType = ElementMarshaller( + arrayType: arrayType, + interfaceType: interfaceType, + convertToUnmanagedInterfaceMethod: interopReferences.IWindowsRuntimeManagedValueTypeArrayElementMarshallerConvertToUnmanaged(elementType, elementAbiType), + convertToManagedInterfaceMethod: interopReferences.IWindowsRuntimeManagedValueTypeArrayElementMarshallerConvertToManaged(elementType, elementAbiType), + isValueType: true, + interopReferences: interopReferences, + emitState: emitState, + module: module); + + // Rewriting labels + CilInstruction nop_dispose = new(Nop); + + // Define the 'Dispose' method as follows: + // + // public static void Dispose( value) + MethodDefinition disposeMethod = new( + name: "Dispose"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic(module.CorLibTypeFactory.Void, elementAbiType.Import(module))) + { + CilInstructions = + { + { Ldarg_0 }, + { nop_dispose }, + { Ret } + } + }; + + // Add and implement the 'Dispose' method + elementMarshallerType.AddMethodImplementation( + declaration: interopReferences.IWindowsRuntimeManagedValueTypeArrayElementMarshallerDispose(elementType, elementAbiType).Import(module), + method: disposeMethod); + + // Track rewriting the disposal for 'Dispose' + emitState.TrackDisposeRewrite( + parameterType: elementType, + method: disposeMethod, + marker: nop_dispose); + + return elementMarshallerType; + } + + /// + /// Creates a for the element marshaller for a type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The emit state for this invocation. + /// The module that will contain the type being created. + /// The resulting element marshaller type. + public static TypeDefinition KeyValuePair( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + GenericInstanceTypeSignature elementType = (GenericInstanceTypeSignature)arrayType.BaseType; + TypeSignature keyType = elementType.TypeArguments[0]; + TypeSignature valueType = elementType.TypeArguments[1]; + + // Get the constructed 'IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller' interface type + TypeSignature interfaceType = interopReferences + .IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller2 + .MakeGenericReferenceType(keyType, valueType); + + // If both the key and the value types are value types, it means the whole marshaller will be specialized. + // In that case we can emit the element marshaller type as a value type as well, so the whole thing can be + // fully specialized and inlined. We don't do this if either type is a reference type, because that means + // the generic instantiation could still be shared between different types, so we prefer to save size there. + bool isValueType = keyType.IsValueType && valueType.IsValueType; + + return ElementMarshaller( + arrayType: arrayType, + interfaceType: interfaceType, + convertToUnmanagedInterfaceMethod: interopReferences.IWindowsRuntimeKeyValuePairTypeArrayElementMarshallerConvertToUnmanaged(keyType, valueType), + convertToManagedInterfaceMethod: interopReferences.IWindowsRuntimeKeyValuePairTypeArrayElementMarshallerConvertToManaged(keyType, valueType), + isValueType: isValueType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + } + + /// + /// Creates a for the element marshaller for a reference type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The emit state for this invocation. + /// The module that will contain the type being created. + /// The resulting element marshaller type. + public static TypeDefinition ReferenceType( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + + // Get the constructed 'IWindowsRuntimeReferenceTypeArrayElementMarshaller' interface type + TypeSignature interfaceType = interopReferences + .IWindowsRuntimeReferenceTypeArrayElementMarshaller1 + .MakeGenericReferenceType(elementType); + + return ElementMarshaller( + arrayType: arrayType, + interfaceType: interfaceType, + convertToUnmanagedInterfaceMethod: interopReferences.IWindowsRuntimeReferenceTypeArrayElementMarshallerConvertToUnmanaged(elementType), + convertToManagedInterfaceMethod: interopReferences.IWindowsRuntimeReferenceTypeArrayElementMarshallerConvertToManaged(elementType), + isValueType: false, + interopReferences: interopReferences, + emitState: emitState, + module: module); + } + + /// + /// Creates a for the element marshaller for some element type. + /// + /// The for the SZ array type. + /// The interface type the element marshaller type should implement. + /// The ConvertToUnmanaged interface method being implemented. + /// The ConvertToManaged interface method being implemented. + /// Indicates whether the element marshaller type should be emitted as a value type. + /// The instance to use. + /// The emit state for this invocation. + /// The module that will contain the type being created. + /// The resulting element marshaller type. + public static TypeDefinition ElementMarshaller( + SzArrayTypeSignature arrayType, + TypeSignature interfaceType, + MemberReference convertToUnmanagedInterfaceMethod, + MemberReference convertToManagedInterfaceMethod, + bool isValueType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + + // Select the attributes and base type depending on whether we want a value type or not + (TypeAttributes attributes, ITypeDefOrRef baseType) = isValueType + ? (TypeAttributes.SequentialLayout | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, interopReferences.ValueType) + : (TypeAttributes.AutoLayout | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit, module.CorLibTypeFactory.Object.ToTypeDefOrRef()); + + // We're declaring an 'internal abstract class' type + TypeDefinition elementMarshallerType = new( + ns: InteropUtf8NameFactory.TypeNamespace(arrayType), + name: InteropUtf8NameFactory.TypeName(arrayType, "ElementMarshaller"), + attributes: attributes, + baseType: baseType) + { + Interfaces = { new InterfaceImplementation(interfaceType.Import(module).ToTypeDefOrRef()) } + }; + + // Rewriting labels + CilInstruction nop_convertToUnmanaged = new(Nop); + CilInstruction nop_convertToManaged = new(Nop); + + // Define the 'ConvertToUnmanaged' method as follows: + // + // public static ConvertToUnmanaged( value) + MethodDefinition convertToUnmanagedMethod = new( + name: "ConvertToUnmanaged"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic( + returnType: elementType.GetRawAbiType(interopReferences).Import(module), + parameterTypes: [elementType.Import(module)])) + { + CilInstructions = + { + { Ldarg_0 }, + { nop_convertToUnmanaged }, + { Ret } + } + }; + + // Add and implement the 'ConvertToUnmanaged' method + elementMarshallerType.AddMethodImplementation( + declaration: convertToUnmanagedInterfaceMethod.Import(module), + method: convertToUnmanagedMethod); + + // Track rewriting the native value for 'ConvertToUnmanaged' + emitState.TrackRawRetValMethodRewrite( + parameterType: elementType, + method: convertToUnmanagedMethod, + marker: nop_convertToUnmanaged); + + // Define the 'ConvertToManaged' method as follows: + // + // public static ConvertToManaged( value) + MethodDefinition convertToManagedMethod = new( + name: "ConvertToManaged"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic( + returnType: elementType.Import(module), + parameterTypes: [elementType.GetAbiType(interopReferences).Import(module)])) + { + CilInstructions = + { + { nop_convertToManaged }, + { Ret } + } + }; + + // Add and implement the 'ConvertToManaged' method + elementMarshallerType.AddMethodImplementation( + declaration: convertToManagedInterfaceMethod.Import(module), + method: convertToManagedMethod); + + // Track rewriting the managed value for 'ConvertToManaged' + emitState.TrackManagedParameterMethodRewrite( + parameterType: elementType, + method: convertToManagedMethod, + marker: nop_convertToManaged, + parameterIndex: 0); + + return elementMarshallerType; + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Factories/InteropTypeDefinitionFactory.SzArrayMarshaller.cs b/src/WinRT.Interop.Generator/Factories/InteropTypeDefinitionFactory.SzArrayMarshaller.cs new file mode 100644 index 000000000..ff7843205 --- /dev/null +++ b/src/WinRT.Interop.Generator/Factories/InteropTypeDefinitionFactory.SzArrayMarshaller.cs @@ -0,0 +1,389 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; +using WindowsRuntime.InteropGenerator.References; +using static AsmResolver.PE.DotNet.Cil.CilOpCodes; + +namespace WindowsRuntime.InteropGenerator.Factories; + +/// +/// A factory for interop type definitions. +/// +internal partial class InteropTypeDefinitionFactory +{ + /// + /// Helpers for marshaller types for SZ array types. + /// + public static class SzArrayMarshaller + { + /// + /// Creates a for the marshaller for a blittable value type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition BlittableValueType( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.WindowsRuntimeBlittableValueTypeArrayMarshallerConvertToUnmanaged(elementType), + convertToManagedMethod: interopReferences.WindowsRuntimeBlittableValueTypeArrayMarshallerConvertToManaged(elementType), + copyToUnmanagedMethod: interopReferences.WindowsRuntimeBlittableValueTypeArrayMarshallerCopyToUnmanaged(elementType), + copyToManagedMethod: interopReferences.WindowsRuntimeBlittableValueTypeArrayMarshallerCopyToManaged(elementType), + freeMethod: interopReferences.WindowsRuntimeBlittableValueTypeArrayMarshallerFree(elementType), + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a for the marshaller for an unmanaged value type. + /// + /// The for the SZ array type. + /// The element marshaller type produced by . + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition UnmanagedValueType( + SzArrayTypeSignature arrayType, + TypeDefinition elementMarshallerType, + InteropReferences interopReferences, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + TypeSignature elementAbiType = elementType.GetAbiType(interopReferences); + TypeSignature elementMarshallerTypeSignature = elementMarshallerType.ToTypeSignature(); + + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.WindowsRuntimeUnmanagedValueTypeArrayMarshallerConvertToUnmanaged(elementType, elementAbiType, elementMarshallerTypeSignature), + convertToManagedMethod: interopReferences.WindowsRuntimeUnmanagedValueTypeArrayMarshallerConvertToManaged(elementType, elementAbiType, elementMarshallerTypeSignature), + copyToUnmanagedMethod: interopReferences.WindowsRuntimeUnmanagedValueTypeArrayMarshallerCopyToUnmanaged(elementType, elementAbiType, elementMarshallerTypeSignature), + copyToManagedMethod: interopReferences.WindowsRuntimeUnmanagedValueTypeArrayMarshallerCopyToManaged(elementType, elementAbiType, elementMarshallerTypeSignature), + freeMethod: interopReferences.WindowsRuntimeUnmanagedValueTypeArrayMarshallerFree(elementType, elementAbiType), + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a for the marshaller for a managed value type. + /// + /// The for the SZ array type. + /// The element marshaller type produced by . + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition ManagedValueType( + SzArrayTypeSignature arrayType, + TypeDefinition elementMarshallerType, + InteropReferences interopReferences, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + TypeSignature elementAbiType = elementType.GetAbiType(interopReferences); + TypeSignature elementMarshallerTypeSignature = elementMarshallerType.ToTypeSignature(); + + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.WindowsRuntimeManagedValueTypeArrayMarshallerConvertToUnmanaged(elementType, elementAbiType, elementMarshallerTypeSignature), + convertToManagedMethod: interopReferences.WindowsRuntimeManagedValueTypeArrayMarshallerConvertToManaged(elementType, elementAbiType, elementMarshallerTypeSignature), + copyToUnmanagedMethod: interopReferences.WindowsRuntimeManagedValueTypeArrayMarshallerCopyToUnmanaged(elementType, elementAbiType, elementMarshallerTypeSignature), + copyToManagedMethod: interopReferences.WindowsRuntimeManagedValueTypeArrayMarshallerCopyToManaged(elementType, elementAbiType, elementMarshallerTypeSignature), + freeMethod: interopReferences.WindowsRuntimeManagedValueTypeArrayMarshallerFree(elementType, elementAbiType, elementMarshallerTypeSignature), + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a for the marshaller for a type. + /// + /// The for the SZ array type. + /// The element marshaller type produced by . + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition KeyValuePair( + SzArrayTypeSignature arrayType, + TypeDefinition elementMarshallerType, + InteropReferences interopReferences, + ModuleDefinition module) + { + GenericInstanceTypeSignature elementType = (GenericInstanceTypeSignature)arrayType.BaseType; + TypeSignature keyType = elementType.TypeArguments[0]; + TypeSignature valueType = elementType.TypeArguments[1]; + TypeSignature elementMarshallerTypeSignature = elementMarshallerType.ToTypeSignature(); + + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.WindowsRuntimeKeyValuePairTypeArrayMarshallerConvertToUnmanaged(keyType, valueType, elementMarshallerTypeSignature), + convertToManagedMethod: interopReferences.WindowsRuntimeKeyValuePairTypeArrayMarshallerConvertToManaged(keyType, valueType, elementMarshallerTypeSignature), + copyToUnmanagedMethod: interopReferences.WindowsRuntimeKeyValuePairTypeArrayMarshallerCopyToUnmanaged(keyType, valueType, elementMarshallerTypeSignature), + copyToManagedMethod: interopReferences.WindowsRuntimeKeyValuePairTypeArrayMarshallerCopyToManaged(keyType, valueType, elementMarshallerTypeSignature), + freeMethod: interopReferences.WindowsRuntimeUnknownArrayMarshallerFree, + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a for the marshaller for a reference type. + /// + /// The for the SZ array type. + /// The element marshaller type produced by . + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition ReferenceType( + SzArrayTypeSignature arrayType, + TypeDefinition elementMarshallerType, + InteropReferences interopReferences, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + TypeSignature elementMarshallerTypeSignature = elementMarshallerType.ToTypeSignature(); + + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.WindowsRuntimeReferenceTypeArrayMarshallerConvertToUnmanaged(elementType, elementMarshallerTypeSignature), + convertToManagedMethod: interopReferences.WindowsRuntimeReferenceTypeArrayMarshallerConvertToManaged(elementType, elementMarshallerTypeSignature), + copyToUnmanagedMethod: interopReferences.WindowsRuntimeReferenceTypeArrayMarshallerCopyToUnmanaged(elementType, elementMarshallerTypeSignature), + copyToManagedMethod: interopReferences.WindowsRuntimeReferenceTypeArrayMarshallerCopyToManaged(elementType, elementMarshallerTypeSignature), + freeMethod: interopReferences.WindowsRuntimeUnknownArrayMarshallerFree, + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a for the marshaller for the type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition String( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + ModuleDefinition module) + { + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.HStringArrayMarshallerConvertToUnmanaged, + convertToManagedMethod: interopReferences.HStringArrayMarshallerConvertToManaged, + copyToUnmanagedMethod: interopReferences.HStringArrayMarshallerCopyToUnmanaged, + copyToManagedMethod: interopReferences.HStringArrayMarshallerCopyToManaged, + freeMethod: interopReferences.HStringArrayMarshallerFree, + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a for the marshaller for the type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition Type( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + ModuleDefinition module) + { + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.TypeArrayMarshallerConvertToUnmanaged, + convertToManagedMethod: interopReferences.TypeArrayMarshallerConvertToManaged, + copyToUnmanagedMethod: interopReferences.TypeArrayMarshallerCopyToUnmanaged, + copyToManagedMethod: interopReferences.TypeArrayMarshallerCopyToManaged, + freeMethod: interopReferences.TypeArrayMarshallerFree, + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a for the marshaller for the type. + /// + /// The for the SZ array type. + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + public static TypeDefinition Exception( + SzArrayTypeSignature arrayType, + InteropReferences interopReferences, + ModuleDefinition module) + { + return Marshaller( + arrayType: arrayType, + convertToUnmanagedMethod: interopReferences.ExceptionArrayMarshallerConvertToUnmanaged, + convertToManagedMethod: interopReferences.ExceptionArrayMarshallerConvertToManaged, + copyToUnmanagedMethod: interopReferences.ExceptionArrayMarshallerCopyToUnmanaged, + copyToManagedMethod: interopReferences.ExceptionArrayMarshallerCopyToManaged, + freeMethod: interopReferences.ExceptionArrayMarshallerFree, + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a new type definition for the marshaller for some SZ array type. + /// + /// The for the SZ array type. + /// The ConvertToUnmanaged implementation method to call. + /// The ConvertToManaged implementation method to call. + /// The CopyToUnmanaged implementation method to call. + /// The CopyToManaged implementation method to call. + /// The Free implementation method to call. + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting marshaller type. + private static TypeDefinition Marshaller( + SzArrayTypeSignature arrayType, + IMethodDescriptor convertToUnmanagedMethod, + IMethodDescriptor convertToManagedMethod, + IMethodDescriptor copyToUnmanagedMethod, + IMethodDescriptor copyToManagedMethod, + IMethodDescriptor freeMethod, + InteropReferences interopReferences, + ModuleDefinition module) + { + TypeSignature elementType = arrayType.BaseType; + TypeSignature elementAbiType = elementType.GetAbiType(interopReferences); + + // We're declaring an 'internal static class' type + TypeDefinition marshallerType = new( + ns: InteropUtf8NameFactory.TypeNamespace(arrayType), + name: InteropUtf8NameFactory.TypeName(arrayType, "Marshaller"), + attributes: TypeAttributes.AutoLayout | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit, + baseType: module.CorLibTypeFactory.Object.ToTypeDefOrRef()); + + // Define the 'ConvertToUnmanaged' method as follows: + // + // public static void ConvertToUnmanaged(ReadOnlySpan<>, out uint size, out * array) + MethodDefinition convertToUnmanagedForwarderMethod = new( + name: "ConvertToUnmanaged"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [ + interopReferences.ReadOnlySpan1.MakeGenericValueType(elementType).Import(module), + module.CorLibTypeFactory.UInt32.MakeByReferenceType(), + elementAbiType.Import(module).MakePointerType().MakeByReferenceType()])) + { + CilOutParameterIndices = [2, 3], + CilInstructions = + { + { Ldarg_0 }, + { Ldarg_1 }, + { Ldarg_2 }, + { Call, convertToUnmanagedMethod.Import(module) }, + { Ret } + } + }; + + marshallerType.Methods.Add(convertToUnmanagedForwarderMethod); + + // Define the 'ConvertToManaged' method as follows: + // + // public static [] ConvertToManaged(uint size, * value) + MethodDefinition convertToManagedForwarderMethod = new( + name: "ConvertToManaged"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic( + returnType: arrayType.Import(module), + parameterTypes: [ + module.CorLibTypeFactory.UInt32, + elementAbiType.Import(module).MakePointerType()])) + { + CilInstructions = + { + { Ldarg_0 }, + { Ldarg_1 }, + { Call, convertToManagedMethod.Import(module) }, + { Ret } + } + }; + + marshallerType.Methods.Add(convertToManagedForwarderMethod); + + // Define the 'CopyToManaged' method as follows: + // + // public static void CopyToManaged(uint size, * value, Span<> destination) + MethodDefinition copyToManagedForwarderMethod = new( + name: "CopyToManaged"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [ + module.CorLibTypeFactory.UInt32, + elementAbiType.Import(module).MakePointerType(), + interopReferences.Span1.MakeGenericValueType(elementType).Import(module)])) + { + CilInstructions = + { + { Ldarg_0 }, + { Ldarg_1 }, + { Ldarg_2 }, + { Call, copyToManagedMethod.Import(module) }, + { Ret } + } + }; + + marshallerType.Methods.Add(copyToManagedForwarderMethod); + + // Define the 'CopyToUnmanaged' method as follows: + // + // public static void CopyToUnmanaged(ReadOnlySpan<> value, uint size, * destination) + MethodDefinition copyToUnmanagedForwarderMethod = new( + name: "CopyToUnmanaged"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [ + interopReferences.ReadOnlySpan1.MakeGenericValueType(elementType).Import(module), + module.CorLibTypeFactory.UInt32, + elementAbiType.Import(module).MakePointerType()])) + { + CilInstructions = + { + { Ldarg_0 }, + { Ldarg_1 }, + { Ldarg_2 }, + { Call, copyToUnmanagedMethod.Import(module) }, + { Ret } + } + }; + + marshallerType.Methods.Add(copyToUnmanagedForwarderMethod); + + // Define the 'Free' method as follows: + // + // public static void Free(uint size, * destination) + MethodDefinition freeForwarderMethod = new( + name: "Free"u8, + attributes: MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [ + module.CorLibTypeFactory.UInt32, + elementAbiType.Import(module).MakePointerType()])) + { + CilInstructions = + { + { Ldarg_0 }, + { Ldarg_1 }, + { Call, freeMethod.Import(module) }, + { Ret } + } + }; + + marshallerType.Methods.Add(freeForwarderMethod); + + return marshallerType; + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Factories/InteropUtf8NameFactory.cs b/src/WinRT.Interop.Generator/Factories/InteropUtf8NameFactory.cs index 10b05f77b..fd47ba213 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropUtf8NameFactory.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropUtf8NameFactory.cs @@ -74,62 +74,41 @@ static void AppendTypeName( return; } - // SZ arrays are enclosed in angle brackets - if (typeSignature is SzArrayTypeSignature) + // SZ arrays are enclosed in angle brackets, and have the 'Array' suffix at the end + if (typeSignature is SzArrayTypeSignature arrayTypeSignature) { interpolatedStringHandler.AppendLiteral("<"); - } - // Each type name uses this format: 'TYPE_NAME' - interpolatedStringHandler.AppendLiteral("<"); - interpolatedStringHandler.AppendFormatted(AssemblyNameOrWellKnownIdentifier(typeSignature.Scope!.GetAssembly()!.Name, typeSignature)); - interpolatedStringHandler.AppendLiteral(">"); + AppendTypeName(ref interpolatedStringHandler, arrayTypeSignature.BaseType, depth); - // If the type is generic, append the definition name and the type arguments - if (typeSignature is GenericInstanceTypeSignature genericInstanceTypeSignature) + interpolatedStringHandler.AppendLiteral(">Array"); + } + else { - // Append the name of the generic type, without any type arguments (those are appended below) - AppendRawTypeName(ref interpolatedStringHandler, genericInstanceTypeSignature.GenericType, depth); - + // Each type name uses this format: 'TYPE_NAME' interpolatedStringHandler.AppendLiteral("<"); + interpolatedStringHandler.AppendFormatted(AssemblyNameOrWellKnownIdentifier(typeSignature.Scope!.GetAssembly()!.Name, typeSignature)); + interpolatedStringHandler.AppendLiteral(">"); - foreach ((int i, TypeSignature typeArgumentSignature) in genericInstanceTypeSignature.TypeArguments.Index()) - { - // We use '|' to separate generic type arguments - if (i > 0) - { - interpolatedStringHandler.AppendLiteral("|"); - } - - // Append the type argument with the same format as the root type. This is - // important to ensure that nested generic types will be handled correctly. - AppendTypeName(ref interpolatedStringHandler, typeArgumentSignature, depth: depth + 1); - } + // Extract the generic type if we have a generic signature, or use the type signature directly + ITypeDescriptor originalTypeDescriptor = ((typeSignature as GenericInstanceTypeSignature)?.GenericType) ?? (ITypeDescriptor)typeSignature; - interpolatedStringHandler.AppendLiteral(">"); - } - else if (typeSignature is SzArrayTypeSignature arrayTypeSignature) - { - // Same as below, but we use the element type name, not the array type name - AppendRawTypeName(ref interpolatedStringHandler, arrayTypeSignature.BaseType, depth); - } - else - { - // Simple case for normal type signatures - AppendRawTypeName(ref interpolatedStringHandler, typeSignature, depth); - } + // Append the original type name first, regardless of whether it's an array or a constructed generic + AppendRawTypeName(ref interpolatedStringHandler, originalTypeDescriptor, depth); - // Complete the name mangling for SZ arrays - if (typeSignature is SzArrayTypeSignature) - { - interpolatedStringHandler.AppendLiteral(">Array"); + // If the type is generic, append the definition name and the type arguments. We pass the original + // type descriptor here, because we also want to detect arrays with an element type that's generic. + if (typeSignature is GenericInstanceTypeSignature genericInstanceTypeSignature) + { + AppendTypeArguments(ref interpolatedStringHandler, genericInstanceTypeSignature, depth); + } } } // Helper to recursively build the type name (to handle nested generic types too) static void AppendRawTypeName( ref DefaultInterpolatedStringHandler interpolatedStringHandler, - IMemberDescriptor type, + ITypeDescriptor type, int depth) { // We can skip the namespace when the indentation level is '0', as that means @@ -166,6 +145,30 @@ static void AppendRawTypeName( } } + // Helper to iteratively print the type arguments for a constructed type + static void AppendTypeArguments( + ref DefaultInterpolatedStringHandler interpolatedStringHandler, + GenericInstanceTypeSignature type, + int depth) + { + interpolatedStringHandler.AppendLiteral("<"); + + foreach ((int i, TypeSignature typeArgumentSignature) in type.TypeArguments.Index()) + { + // We use '|' to separate generic type arguments + if (i > 0) + { + interpolatedStringHandler.AppendLiteral("|"); + } + + // Append the type argument with the same format as the root type. This is + // important to ensure that nested generic types will be handled correctly. + AppendTypeName(ref interpolatedStringHandler, typeArgumentSignature, depth: depth + 1); + } + + interpolatedStringHandler.AppendLiteral(">"); + } + // Append the full type name first AppendTypeName(ref interpolatedStringHandler, typeSignature, depth: 0); diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs index 4a92f1f3c..260bf0324 100644 --- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs +++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs @@ -135,7 +135,7 @@ private static void Emit(InteropGeneratorArgs args, InteropGeneratorDiscoverySta args.Token.ThrowIfCancellationRequested(); // Emit interop types for SZ array types - DefineSzArrayTypes(args, discoveryState, interopDefinitions, interopReferences, module); + DefineSzArrayTypes(args, discoveryState, emitState, interopDefinitions, interopReferences, module); args.Token.ThrowIfCancellationRequested(); @@ -1905,12 +1905,14 @@ private static void DefineIAsyncOperationWithProgressTypes( /// /// /// + /// The emit state for this invocation. /// The instance to use. /// The instance to use. /// The interop module being built. private static void DefineSzArrayTypes( InteropGeneratorArgs args, InteropGeneratorDiscoveryState discoveryState, + InteropGeneratorEmitState emitState, InteropDefinitions interopDefinitions, InteropReferences interopReferences, ModuleDefinition module) @@ -1932,6 +1934,7 @@ private static void DefineSzArrayTypes( InteropTypeDefinitionBuilder.SzArray.Marshaller( arrayType: typeSignature, interopReferences: interopReferences, + emitState: emitState, module: module, marshallerType: out TypeDefinition marshallerType); @@ -2017,6 +2020,17 @@ private static void RewriteMethodDefinitions( { switch (rewriteInfo) { + // Rewrite direct calls to 'ConvertToUnmanaged' (or 'BoxToUnmanaged') + case MethodRewriteInfo.RawRetVal rawRetValInfo: + InteropMethodRewriteFactory.RawRetVal.RewriteMethod( + parameterType: rawRetValInfo.Type, + method: rawRetValInfo.Method, + marker: rawRetValInfo.Marker, + interopReferences: interopReferences, + emitState: emitState, + module: module); + break; + // Rewrite return values for managed types case MethodRewriteInfo.ReturnValue returnValueInfo: InteropMethodRewriteFactory.ReturnValue.RewriteMethod( @@ -2076,6 +2090,17 @@ private static void RewriteMethodDefinitions( emitState: emitState, module: module); break; + + // Rewrite direct calls to 'Dispose' (or the appropriate 'Free' method) + case MethodRewriteInfo.Dispose disposeInfo: + InteropMethodRewriteFactory.Dispose.RewriteMethod( + parameterType: disposeInfo.Type, + method: disposeInfo.Method, + marker: disposeInfo.Marker, + interopReferences: interopReferences, + emitState: emitState, + module: module); + break; default: throw new UnreachableException(); } } diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs index 1009530b2..495204504 100644 --- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs +++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs @@ -132,6 +132,27 @@ public void TrackRetValValueMethodRewrite( }); } + /// + /// Tracks a method rewrite that involves emitting direct calls to ConvertToUnmanaged in the specified method. + /// + /// + /// + /// + public void TrackRawRetValMethodRewrite( + TypeSignature parameterType, + MethodDefinition method, + CilInstruction marker) + { + ThrowIfReadOnly(); + + _methodRewriteInfos.Add(new MethodRewriteInfo.RawRetVal + { + Type = parameterType, + Method = method, + Marker = marker + }); + } + /// /// Tracks a method rewrite that involves loading a managed parameter in the specified method. /// @@ -207,6 +228,27 @@ public void TrackNativeParameterMethodRewrite( }); } + /// + /// Tracks a method rewrite that involves emitting calls to dispose (or release) a given value in the specified method. + /// + /// + /// + /// + public void TrackDisposeRewrite( + TypeSignature parameterType, + MethodDefinition method, + CilInstruction marker) + { + ThrowIfReadOnly(); + + _methodRewriteInfos.Add(new MethodRewriteInfo.Dispose + { + Type = parameterType, + Method = method, + Marker = marker + }); + } + /// /// Enumerates all instances with info on two-pass code generation steps to perform. /// diff --git a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.Dispose.cs b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.Dispose.cs new file mode 100644 index 000000000..e3f8cbb25 --- /dev/null +++ b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.Dispose.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace WindowsRuntime.InteropGenerator.Models; + +/// +internal partial class MethodRewriteInfo +{ + /// + /// Contains info for a target method for two-pass IL generation, to dispose (or release) a given value. + /// + /// + public sealed class Dispose : MethodRewriteInfo + { + /// + public override int CompareTo(MethodRewriteInfo? other) + { + // 'Dispose' objects have no additional state, so just compare with the base state + return ReferenceEquals(this, other) + ? 0 + : CompareByMethodRewriteInfo(other); + } + } +} diff --git a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.RawRetVal.cs b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.RawRetVal.cs new file mode 100644 index 000000000..730ce5362 --- /dev/null +++ b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.RawRetVal.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace WindowsRuntime.InteropGenerator.Models; + +/// +internal partial class MethodRewriteInfo +{ + /// + /// Contains info for a target method for two-pass IL generation, for emitting direct calls to ConvertToUnmanaged. + /// + /// + public sealed class RawRetVal : MethodRewriteInfo + { + /// + public override int CompareTo(MethodRewriteInfo? other) + { + // 'RawRetVal' objects have no additional state, so just compare with the base state + return ReferenceEquals(this, other) + ? 0 + : CompareByMethodRewriteInfo(other); + } + } +} diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index 67b51c00d..0cd5ae3ad 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -903,6 +903,71 @@ public InteropReferences( /// public TypeReference WindowsRuntimeArrayMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeArrayMarshaller"u8); + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeBlittableValueTypeArrayMarshaller<T>. + /// + public TypeReference WindowsRuntimeBlittableValueTypeArrayMarshaller1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeBlittableValueTypeArrayMarshaller`1"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeManagedValueTypeArrayMarshaller<T, TAbi>. + /// + public TypeReference WindowsRuntimeManagedValueTypeArrayMarshaller2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeManagedValueTypeArrayMarshaller`2"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnmanagedValueTypeArrayMarshaller<T, TAbi>. + /// + public TypeReference WindowsRuntimeUnmanagedValueTypeArrayMarshaller2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeUnmanagedValueTypeArrayMarshaller`2"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeReferenceTypeArrayMarshaller<T>. + /// + public TypeReference WindowsRuntimeReferenceTypeArrayMarshaller1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeReferenceTypeArrayMarshaller`1"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnknownArrayMarshaller. + /// + public TypeReference WindowsRuntimeUnknownArrayMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeUnknownArrayMarshaller"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeKeyValuePairTypeArrayMarshaller<TKey, TValue>. + /// + public TypeReference WindowsRuntimeKeyValuePairTypeArrayMarshaller2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeKeyValuePairTypeArrayMarshaller`2"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeReferenceTypeArrayElementMarshaller<T>. + /// + public TypeReference IWindowsRuntimeReferenceTypeArrayElementMarshaller1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "IWindowsRuntimeReferenceTypeArrayElementMarshaller`1"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeManagedValueTypeArrayElementMarshaller<T, TAbi>. + /// + public TypeReference IWindowsRuntimeManagedValueTypeArrayElementMarshaller2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "IWindowsRuntimeManagedValueTypeArrayElementMarshaller`2"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller<T, TAbi>. + /// + public TypeReference IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller`2"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller<TKey, TValue>. + /// + public TypeReference IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller`2"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.TypeArrayMarshaller. + /// + public TypeReference TypeArrayMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "TypeArrayMarshaller"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.HStringArrayMarshaller. + /// + public TypeReference HStringArrayMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "HStringArrayMarshaller"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.ExceptionArrayMarshaller. + /// + public TypeReference ExceptionArrayMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "ExceptionArrayMarshaller"u8); + /// /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeValueTypeMarshaller. /// @@ -928,11 +993,6 @@ public InteropReferences( /// public TypeReference RestrictedErrorInfo => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "RestrictedErrorInfo"u8); - /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayHelpers. - /// - public TypeReference WindowsRuntimeArrayHelpers => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeArrayHelpers"u8); - /// /// Gets the for WindowsRuntime.InteropServices.Marshalling.RestrictedErrorInfoExceptionMarshaller. /// @@ -1836,6 +1896,175 @@ public InteropReferences( _corLibTypeFactory.Void.MakePointerType(), Guid.ToValueTypeSignature().MakeByReferenceType()])); + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnknownArrayMarshaller.Free. + /// + public MemberReference WindowsRuntimeUnknownArrayMarshallerFree => field ??= WindowsRuntimeUnknownArrayMarshaller + .CreateMemberReference("Free"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.TypeArrayMarshaller.ConvertToUnmanaged. + /// + public MemberReference TypeArrayMarshallerConvertToUnmanaged => field ??= TypeArrayMarshaller + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(Type.ToTypeSignature()), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + AbiType.ToValueTypeSignature().MakePointerType().MakeByReferenceType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.TypeArrayMarshaller.ConvertToManaged. + /// + public MemberReference TypeArrayMarshallerConvertToManaged => field ??= TypeArrayMarshaller + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: Type.ToReferenceTypeSignature().MakeSzArrayType(), + parameterTypes: [ + _corLibTypeFactory.UInt32, + AbiType.ToValueTypeSignature().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.TypeArrayMarshaller.CopyToUnmanaged. + /// + public MemberReference TypeArrayMarshallerCopyToUnmanaged => field ??= TypeArrayMarshaller + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(Type.ToTypeSignature()), + _corLibTypeFactory.UInt32, + AbiType.ToValueTypeSignature().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.TypeArrayMarshaller.CopyToManaged. + /// + public MemberReference TypeArrayMarshallerCopyToManaged => field ??= TypeArrayMarshaller + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + AbiType.ToValueTypeSignature().MakePointerType(), + Span1.MakeGenericValueType(Type.ToTypeSignature())])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.TypeArrayMarshaller.Free. + /// + public MemberReference TypeArrayMarshallerFree => field ??= TypeArrayMarshaller + .CreateMemberReference("Free"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + AbiType.ToValueTypeSignature().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.HStringArrayMarshaller.ConvertToUnmanaged. + /// + public MemberReference HStringArrayMarshallerConvertToUnmanaged => field ??= HStringArrayMarshaller + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(_corLibTypeFactory.String), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + _corLibTypeFactory.Void.MakePointerType().MakePointerType().MakeByReferenceType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.HStringArrayMarshaller.ConvertToManaged. + /// + public MemberReference HStringArrayMarshallerConvertToManaged => field ??= HStringArrayMarshaller + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.String.MakeSzArrayType(), + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.HStringArrayMarshaller.CopyToUnmanaged. + /// + public MemberReference HStringArrayMarshallerCopyToUnmanaged => field ??= HStringArrayMarshaller + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(_corLibTypeFactory.String), + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.HStringArrayMarshaller.CopyToManaged. + /// + public MemberReference HStringArrayMarshallerCopyToManaged => field ??= HStringArrayMarshaller + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType(), + Span1.MakeGenericValueType(_corLibTypeFactory.String)])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.HStringArrayMarshaller.Free. + /// + public MemberReference HStringArrayMarshallerFree => field ??= HStringArrayMarshaller + .CreateMemberReference("Free"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.ExceptionArrayMarshaller.ConvertToUnmanaged. + /// + public MemberReference ExceptionArrayMarshallerConvertToUnmanaged => field ??= ExceptionArrayMarshaller + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(Exception.ToReferenceTypeSignature()), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + AbiException.ToValueTypeSignature().MakePointerType().MakeByReferenceType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.ExceptionArrayMarshaller.ConvertToManaged. + /// + public MemberReference ExceptionArrayMarshallerConvertToManaged => field ??= ExceptionArrayMarshaller + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: Exception.ToReferenceTypeSignature().MakeSzArrayType(), + parameterTypes: [ + _corLibTypeFactory.UInt32, + AbiException.ToValueTypeSignature().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.ExceptionArrayMarshaller.CopyToUnmanaged. + /// + public MemberReference ExceptionArrayMarshallerCopyToUnmanaged => field ??= ExceptionArrayMarshaller + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(Exception.ToReferenceTypeSignature()), + _corLibTypeFactory.UInt32, + AbiException.ToValueTypeSignature().MakePointerType()])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.ExceptionArrayMarshaller.CopyToManaged. + /// + public MemberReference ExceptionArrayMarshallerCopyToManaged => field ??= ExceptionArrayMarshaller + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + AbiException.ToValueTypeSignature().MakePointerType(), + Span1.MakeGenericValueType(Exception.ToReferenceTypeSignature())])); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.ExceptionArrayMarshaller.Free. + /// + public MemberReference ExceptionArrayMarshallerFree => field ??= ExceptionArrayMarshaller + .CreateMemberReference("Free"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + AbiException.ToValueTypeSignature().MakePointerType()])); + /// /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeValueTypeMarshaller.ConvertToUnmanagedUnsafe. /// @@ -1920,52 +2149,609 @@ public InteropReferences( parameterTypes: [_corLibTypeFactory.Int32])); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayHelpers.FreeHStringArrayUnsafe. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.RestrictedErrorInfoExceptionMarshaller.ConvertToUnmanaged(Exception). /// - public MemberReference WindowsRuntimeArrayHelpersFreeHStringArrayUnsafe => field ??= WindowsRuntimeArrayHelpers - .CreateMemberReference("FreeHStringArrayUnsafe"u8, MethodSignature.CreateStatic( - returnType: _corLibTypeFactory.Void, - parameterTypes: [ - _corLibTypeFactory.UInt32, - _corLibTypeFactory.Void.MakePointerType().MakePointerType()])); + public MemberReference RestrictedErrorInfoExceptionMarshallerConvertToUnmanaged => field ??= RestrictedErrorInfoExceptionMarshaller + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Int32, + parameterTypes: [new TypeReference(_corLibTypeFactory.CorLibScope, "System"u8, "Exception"u8).ToReferenceTypeSignature()])); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayHelpers.FreeObjectArrayUnsafe. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeReferenceTypeArrayElementMarshaller<T>.ConvertToUnmanaged. /// - public MemberReference WindowsRuntimeArrayHelpersFreeObjectArrayUnsafe => field ??= WindowsRuntimeArrayHelpers - .CreateMemberReference("FreeObjectArrayUnsafe"u8, MethodSignature.CreateStatic( - returnType: _corLibTypeFactory.Void, - parameterTypes: [ - _corLibTypeFactory.UInt32, - _corLibTypeFactory.Void.MakePointerType().MakePointerType()])); + /// The input element type. + public MemberReference IWindowsRuntimeReferenceTypeArrayElementMarshallerConvertToUnmanaged(TypeSignature elementType) + { + return IWindowsRuntimeReferenceTypeArrayElementMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: WindowsRuntimeObjectReferenceValue.ToValueTypeSignature(), + parameterTypes: [new GenericParameterSignature(GenericParameterType.Type, 0)])); + } /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayHelpers.FreeTypeArrayUnsafe. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeReferenceTypeArrayElementMarshaller<T>.ConvertToManaged. /// - public MemberReference WindowsRuntimeArrayHelpersFreeTypeArrayUnsafe => field ??= WindowsRuntimeArrayHelpers - .CreateMemberReference("FreeTypeArrayUnsafe"u8, MethodSignature.CreateStatic( - returnType: _corLibTypeFactory.Void, - parameterTypes: [ - _corLibTypeFactory.UInt32, - AbiType.ToValueTypeSignature().MakePointerType()])); + /// The input element type. + public MemberReference IWindowsRuntimeReferenceTypeArrayElementMarshallerConvertToManaged(TypeSignature elementType) + { + return IWindowsRuntimeReferenceTypeArrayElementMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0), + parameterTypes: [_corLibTypeFactory.Void.MakePointerType()])); + } /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayHelpers.FreeBlittableArrayUnsafe. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeManagedValueTypeArrayElementMarshaller<T, TAbi>.ConvertToUnmanaged. /// - public MemberReference WindowsRuntimeArrayHelpersFreeBlittableArrayUnsafe => field ??= WindowsRuntimeArrayHelpers - .CreateMemberReference("FreeBlittableArrayUnsafe"u8, MethodSignature.CreateStatic( - returnType: _corLibTypeFactory.Void, - parameterTypes: [ - _corLibTypeFactory.UInt32, - _corLibTypeFactory.Void.MakePointerType()])); + /// The input element type. + /// The ABI type. + public MemberReference IWindowsRuntimeManagedValueTypeArrayElementMarshallerConvertToUnmanaged(TypeSignature elementType, TypeSignature abiType) + { + return IWindowsRuntimeManagedValueTypeArrayElementMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 1), + parameterTypes: [new GenericParameterSignature(GenericParameterType.Type, 0)])); + } /// - /// Gets the for WindowsRuntime.InteropServices.Marshalling.RestrictedErrorInfoExceptionMarshaller.ConvertToUnmanaged(Exception). + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeManagedValueTypeArrayElementMarshaller<T, TAbi>.ConvertToManaged. /// - public MemberReference RestrictedErrorInfoExceptionMarshallerConvertToUnmanaged => field ??= RestrictedErrorInfoExceptionMarshaller - .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( - returnType: _corLibTypeFactory.Int32, - parameterTypes: [new TypeReference(_corLibTypeFactory.CorLibScope, "System"u8, "Exception"u8).ToReferenceTypeSignature()])); + /// The input element type. + /// The ABI type. + public MemberReference IWindowsRuntimeManagedValueTypeArrayElementMarshallerConvertToManaged(TypeSignature elementType, TypeSignature abiType) + { + return IWindowsRuntimeManagedValueTypeArrayElementMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0), + parameterTypes: [new GenericParameterSignature(GenericParameterType.Type, 1)])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeManagedValueTypeArrayElementMarshaller<T, TAbi>.Dispose. + /// + /// The input element type. + /// The ABI type. + public MemberReference IWindowsRuntimeManagedValueTypeArrayElementMarshallerDispose(TypeSignature elementType, TypeSignature abiType) + { + return IWindowsRuntimeManagedValueTypeArrayElementMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("Dispose"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [new GenericParameterSignature(GenericParameterType.Type, 1)])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller<T, TAbi>.ConvertToUnmanaged. + /// + /// The input element type. + /// The ABI type. + public MemberReference IWindowsRuntimeUnmanagedValueTypeArrayElementMarshallerConvertToUnmanaged(TypeSignature elementType, TypeSignature abiType) + { + return IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 1), + parameterTypes: [new GenericParameterSignature(GenericParameterType.Type, 0)])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller<T, TAbi>.ConvertToManaged. + /// + /// The input element type. + /// The ABI type. + public MemberReference IWindowsRuntimeUnmanagedValueTypeArrayElementMarshallerConvertToManaged(TypeSignature elementType, TypeSignature abiType) + { + return IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0), + parameterTypes: [new GenericParameterSignature(GenericParameterType.Type, 1)])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller<TKey, TValue>.ConvertToUnmanaged. + /// + /// The input key type. + /// The input value type. + public MemberReference IWindowsRuntimeKeyValuePairTypeArrayElementMarshallerConvertToUnmanaged(TypeSignature keyType, TypeSignature valueType) + { + return IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller2 + .MakeGenericReferenceType(keyType, valueType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: WindowsRuntimeObjectReferenceValue.ToValueTypeSignature(), + parameterTypes: [ + KeyValuePair2.MakeGenericValueType( + new GenericParameterSignature(GenericParameterType.Type, 0), + new GenericParameterSignature(GenericParameterType.Type, 1))])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller<TKey, TValue>.ConvertToManaged. + /// + /// The input key type. + /// The input value type. + public MemberReference IWindowsRuntimeKeyValuePairTypeArrayElementMarshallerConvertToManaged(TypeSignature keyType, TypeSignature valueType) + { + return IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller2 + .MakeGenericReferenceType(keyType, valueType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: KeyValuePair2.MakeGenericValueType( + new GenericParameterSignature(GenericParameterType.Type, 0), + new GenericParameterSignature(GenericParameterType.Type, 1)), + parameterTypes: [_corLibTypeFactory.Void.MakePointerType()])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeBlittableValueTypeArrayMarshaller<T>.ConvertToUnmanaged. + /// + /// The input element type. + public MemberReference WindowsRuntimeBlittableValueTypeArrayMarshallerConvertToUnmanaged(TypeSignature elementType) + { + return WindowsRuntimeBlittableValueTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + new GenericParameterSignature(GenericParameterType.Type, 0).MakePointerType().MakeByReferenceType()])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeBlittableValueTypeArrayMarshaller<T>.ConvertToManaged. + /// + /// The input element type. + public MemberReference WindowsRuntimeBlittableValueTypeArrayMarshallerConvertToManaged(TypeSignature elementType) + { + return WindowsRuntimeBlittableValueTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0).MakeSzArrayType(), + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 0).MakePointerType()])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeBlittableValueTypeArrayMarshaller<T>.CopyToUnmanaged. + /// + /// The input element type. + public MemberReference WindowsRuntimeBlittableValueTypeArrayMarshallerCopyToUnmanaged(TypeSignature elementType) + { + return WindowsRuntimeBlittableValueTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 0).MakePointerType()])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeBlittableValueTypeArrayMarshaller<T>.CopyToManaged. + /// + /// The input element type. + public MemberReference WindowsRuntimeBlittableValueTypeArrayMarshallerCopyToManaged(TypeSignature elementType) + { + return WindowsRuntimeBlittableValueTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 0).MakePointerType(), + Span1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0))])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeBlittableValueTypeArrayMarshaller<T>.Free. + /// + /// The input element type. + public MemberReference WindowsRuntimeBlittableValueTypeArrayMarshallerFree(TypeSignature elementType) + { + return WindowsRuntimeBlittableValueTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("Free"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 0).MakePointerType()])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeManagedValueTypeArrayMarshaller<T, TAbi>.ConvertToUnmanaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeManagedValueTypeArrayMarshallerConvertToUnmanaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeManagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType().MakeByReferenceType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeManagedValueTypeArrayMarshaller<T, TAbi>.ConvertToManaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeManagedValueTypeArrayMarshallerConvertToManaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeManagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0).MakeSzArrayType(), + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeManagedValueTypeArrayMarshaller<T, TAbi>.CopyToUnmanaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeManagedValueTypeArrayMarshallerCopyToUnmanaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeManagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeManagedValueTypeArrayMarshaller<T, TAbi>.CopyToManaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeManagedValueTypeArrayMarshallerCopyToManaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeManagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType(), + Span1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0))])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeManagedValueTypeArrayMarshaller<T, TAbi>.Free<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeManagedValueTypeArrayMarshallerFree(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeManagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("Free"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnmanagedValueTypeArrayMarshaller<T, TAbi>.ConvertToUnmanaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeUnmanagedValueTypeArrayMarshallerConvertToUnmanaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeUnmanagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType().MakeByReferenceType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnmanagedValueTypeArrayMarshaller<T, TAbi>.ConvertToManaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeUnmanagedValueTypeArrayMarshallerConvertToManaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeUnmanagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0).MakeSzArrayType(), + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnmanagedValueTypeArrayMarshaller<T, TAbi>.CopyToUnmanaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeUnmanagedValueTypeArrayMarshallerCopyToUnmanaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeUnmanagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnmanagedValueTypeArrayMarshaller<T, TAbi>.CopyToManaged<TElementMarshaller>. + /// + /// The input element type. + /// The ABI type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeUnmanagedValueTypeArrayMarshallerCopyToManaged(TypeSignature elementType, TypeSignature abiType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeUnmanagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType(), + Span1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0))])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnmanagedValueTypeArrayMarshaller<T, TAbi>.Free. + /// + /// The input element type. + /// The ABI type. + public MemberReference WindowsRuntimeUnmanagedValueTypeArrayMarshallerFree(TypeSignature elementType, TypeSignature abiType) + { + return WindowsRuntimeUnmanagedValueTypeArrayMarshaller2 + .MakeGenericReferenceType(elementType, abiType) + .ToTypeDefOrRef() + .CreateMemberReference("Free"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.UInt32, + new GenericParameterSignature(GenericParameterType.Type, 1).MakePointerType()])); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeReferenceTypeArrayMarshaller<T>.ConvertToUnmanaged<TElementMarshaller>. + /// + /// The input element type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeReferenceTypeArrayMarshallerConvertToUnmanaged(TypeSignature elementType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeReferenceTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + _corLibTypeFactory.Void.MakePointerType().MakePointerType().MakeByReferenceType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeReferenceTypeArrayMarshaller<T>.ConvertToManaged<TElementMarshaller>. + /// + /// The input element type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeReferenceTypeArrayMarshallerConvertToManaged(TypeSignature elementType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeReferenceTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0).MakeSzArrayType(), + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeReferenceTypeArrayMarshaller<T>.CopyToUnmanaged<TElementMarshaller>. + /// + /// The input element type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeReferenceTypeArrayMarshallerCopyToUnmanaged(TypeSignature elementType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeReferenceTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0)), + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeReferenceTypeArrayMarshaller<T>.CopyToManaged<TElementMarshaller>. + /// + /// The input element type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeReferenceTypeArrayMarshallerCopyToManaged(TypeSignature elementType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeReferenceTypeArrayMarshaller1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType(), + Span1.MakeGenericValueType(new GenericParameterSignature(GenericParameterType.Type, 0))])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeKeyValuePairTypeArrayMarshaller<TKey, TValue>.ConvertToUnmanaged<TElementMarshaller>. + /// + /// The input key type. + /// The input value type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeKeyValuePairTypeArrayMarshallerConvertToUnmanaged(TypeSignature keyType, TypeSignature valueType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeKeyValuePairTypeArrayMarshaller2 + .MakeGenericReferenceType(keyType, valueType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType( + KeyValuePair2.MakeGenericValueType( + new GenericParameterSignature(GenericParameterType.Type, 0), + new GenericParameterSignature(GenericParameterType.Type, 1))), + _corLibTypeFactory.UInt32.MakeByReferenceType(), + _corLibTypeFactory.Void.MakePointerType().MakePointerType().MakeByReferenceType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeKeyValuePairTypeArrayMarshaller<TKey, TValue>.ConvertToManaged<TElementMarshaller>. + /// + /// The input key type. + /// The input value type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeKeyValuePairTypeArrayMarshallerConvertToManaged(TypeSignature keyType, TypeSignature valueType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeKeyValuePairTypeArrayMarshaller2 + .MakeGenericReferenceType(keyType, valueType) + .ToTypeDefOrRef() + .CreateMemberReference("ConvertToManaged"u8, MethodSignature.CreateStatic( + returnType: KeyValuePair2.MakeGenericValueType( + new GenericParameterSignature(GenericParameterType.Type, 0), + new GenericParameterSignature(GenericParameterType.Type, 1)).MakeSzArrayType(), + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeKeyValuePairTypeArrayMarshaller<TKey, TValue>.CopyToUnmanaged<TElementMarshaller>. + /// + /// The input key type. + /// The input value type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeKeyValuePairTypeArrayMarshallerCopyToUnmanaged(TypeSignature keyType, TypeSignature valueType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeKeyValuePairTypeArrayMarshaller2 + .MakeGenericReferenceType(keyType, valueType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToUnmanaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + ReadOnlySpan1.MakeGenericValueType( + KeyValuePair2.MakeGenericValueType( + new GenericParameterSignature(GenericParameterType.Type, 0), + new GenericParameterSignature(GenericParameterType.Type, 1))), + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType()])) + .MakeGenericInstanceMethod(elementMarshallerType); + } + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeKeyValuePairTypeArrayMarshaller<TKey, TValue>.CopyToManaged<TElementMarshaller>. + /// + /// The input key type. + /// The input value type. + /// The element marshaller type. + public MethodSpecification WindowsRuntimeKeyValuePairTypeArrayMarshallerCopyToManaged(TypeSignature keyType, TypeSignature valueType, TypeSignature elementMarshallerType) + { + return WindowsRuntimeKeyValuePairTypeArrayMarshaller2 + .MakeGenericReferenceType(keyType, valueType) + .ToTypeDefOrRef() + .CreateMemberReference("CopyToManaged"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + genericParameterCount: 1, + parameterTypes: [ + _corLibTypeFactory.UInt32, + _corLibTypeFactory.Void.MakePointerType().MakePointerType(), + Span1.MakeGenericValueType( + KeyValuePair2.MakeGenericValueType( + new GenericParameterSignature(GenericParameterType.Type, 0), + new GenericParameterSignature(GenericParameterType.Type, 1)))])) + .MakeGenericInstanceMethod(elementMarshallerType); + } /// /// Gets the for AddEventHandler for . diff --git a/src/WinRT.Runtime2/InteropServices/Events/EventSource{T}.cs b/src/WinRT.Runtime2/InteropServices/Events/EventSource{T}.cs index bffbb9b7f..74befaccb 100644 --- a/src/WinRT.Runtime2/InteropServices/Events/EventSource{T}.cs +++ b/src/WinRT.Runtime2/InteropServices/Events/EventSource{T}.cs @@ -88,7 +88,7 @@ public void Subscribe(T? handler) // That CCW will point the event invoker, ie. a stub on the event source state object. // This stub captures the event source state, and just invokes the target delegate. // If we don't need to register the handler, we still just add the new handler here. - // THe existing CCW will just pick it up the next time the native event is invoked. + // The existing CCW will just pick it up the next time the native event is invoked. state!.AddHandler(handler); if (registerHandler) diff --git a/src/WinRT.Runtime2/InteropServices/InteropDllExports/WindowsRuntimeArrayHelpers.cs b/src/WinRT.Runtime2/InteropServices/InteropDllExports/WindowsRuntimeArrayHelpers.cs deleted file mode 100644 index 904001354..000000000 --- a/src/WinRT.Runtime2/InteropServices/InteropDllExports/WindowsRuntimeArrayHelpers.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using WindowsRuntime.InteropServices.Marshalling; - -namespace WindowsRuntime.InteropServices; - -/// -/// A helper for generated marshaller types for Windows Runtime arrays. -/// -[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, - DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, - UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] -[EditorBrowsable(EditorBrowsableState.Never)] -public static unsafe class WindowsRuntimeArrayHelpers -{ - /// - /// Validates that the specified destination span has the required number of elements. - /// - /// The type of elements in the destination span. - /// The expected number of elements in the destination span. - /// The span to validate. - /// Thrown if the length of does not equal . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [StackTraceHidden] - public static void ValidateDestinationSize(uint size, Span destination) - { - if (destination.Length != size) - { - [StackTraceHidden] - static void ThrowArgumentException() => throw new ArgumentException("The destination array is too small.", nameof(destination)); - - ThrowArgumentException(); - } - } - - /// - /// Validates that the specified destination span has the required number of elements. - /// - /// The type of elements in the destination span. - /// The span to validate. - /// The expected number of elements in the destination span. - /// Thrown if the length of does not equal . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [StackTraceHidden] - public static void ValidateDestinationSize(ReadOnlySpan source, uint size) - { - if (source.Length != size) - { - [StackTraceHidden] - static void ThrowArgumentException() => throw new ArgumentException("The destination array is too small.", "destination"); - - ThrowArgumentException(); - } - } - - /// - /// Frees an HSTRING reference array. - /// - /// The size of the array. - /// The input array. - [MethodImpl(MethodImplOptions.NoInlining)] - public static void FreeHStringArrayUnsafe(uint size, HSTRING* array) - { - if (size == 0) - { - return; - } - - ArgumentNullException.ThrowIfNull(array); - - for (int i = 0; i < size; i++) - { - HStringMarshaller.Free(array[i]); - } - - Marshal.FreeCoTaskMem((nint)array); - } - - /// - /// Frees an object reference array. - /// - /// The size of the array. - /// The input array. - [MethodImpl(MethodImplOptions.NoInlining)] - public static void FreeObjectArrayUnsafe(uint size, void** array) - { - if (size == 0) - { - return; - } - - ArgumentNullException.ThrowIfNull(array); - - for (int i = 0; i < size; i++) - { - WindowsRuntimeUnknownMarshaller.Free(array[i]); - } - - Marshal.FreeCoTaskMem((nint)array); - } - - /// - /// Frees a reference array of values. - /// - /// The size of the array. - /// The input array. - [MethodImpl(MethodImplOptions.NoInlining)] - public static void FreeTypeArrayUnsafe(uint size, ABI.System.Type* array) - { - if (size == 0) - { - return; - } - - ArgumentNullException.ThrowIfNull(array); - - for (int i = 0; i < size; i++) - { - HStringMarshaller.Free(array[i].Name); - } - - Marshal.FreeCoTaskMem((nint)array); - } - - /// - /// Frees a reference array of some blittable type. - /// - /// The size of the array. - /// The input array. - [MethodImpl(MethodImplOptions.NoInlining)] - public static void FreeBlittableArrayUnsafe(uint size, void* array) - { - if (size == 0) - { - return; - } - - ArgumentNullException.ThrowIfNull(array); - - Marshal.FreeCoTaskMem((nint)array); - } - - /// - /// Frees a range of an HSTRING reference array. - /// - /// The offset to free the array up to. - /// The input array. - [MethodImpl(MethodImplOptions.NoInlining)] - public static void FreeHStringRangeUnsafe(int offset, HSTRING* array) - { - for (int i = 0; i < offset; i++) - { - HStringMarshaller.Free(array[i]); - } - } - - /// - /// Frees a range of an object reference array. - /// - /// The offset to free the array up to. - /// The input array. - [MethodImpl(MethodImplOptions.NoInlining)] - public static void FreeObjectRangeUnsafe(int offset, void** array) - { - for (int i = 0; i < offset; i++) - { - WindowsRuntimeUnknownMarshaller.Free(array[i]); - } - } -} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/ExceptionArrayMarshaller.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/ExceptionArrayMarshaller.cs new file mode 100644 index 000000000..ff19124bc --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/ExceptionArrayMarshaller.cs @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of the Windows Runtime type. +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class ExceptionArrayMarshaller +{ + /// + public static void ConvertToUnmanaged(ReadOnlySpan source, out uint size, out ABI.System.Exception* array) + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + ABI.System.Exception* destination = (ABI.System.Exception*)Marshal.AllocCoTaskMem(sizeof(ABI.System.Exception) * source.Length); + + try + { + // Marshal all input 'Exception'-s with 'ExceptionMarshaller' (note that 'HResult' is blittable) + for (int i = 0; i < source.Length; i++) + { + destination[i] = ABI.System.ExceptionMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // Release the allocated array to avoid leaking (this shouldn't really happen) + Marshal.FreeCoTaskMem((nint)destination); + + throw; + } + + size = (uint)source.Length; + array = destination; + } + + /// + public static Exception?[] ConvertToManaged(uint size, ABI.System.Exception* value) + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + Exception?[] array = new Exception[(int)size]; + + for (int i = 0; i < size; i++) + { + array[i] = ABI.System.ExceptionMarshaller.ConvertToManaged(value[i]); + } + + return array; + } + + /// + public static void CopyToUnmanaged(ReadOnlySpan source, uint size, ABI.System.Exception* destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + for (int i = 0; i < source.Length; i++) + { + destination[i] = ABI.System.ExceptionMarshaller.ConvertToUnmanaged(source[i]); + } + } + + /// + public static void CopyToManaged(uint size, ABI.System.Exception* source, Span destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + for (uint i = 0; i < size; i++) + { + destination[(int)i] = ABI.System.ExceptionMarshaller.ConvertToManaged(source[i]); + } + } + + /// + public static void Free(uint size, ABI.System.Exception* array) + { + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(array); + + Marshal.FreeCoTaskMem((nint)array); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/HStringArrayMarshaller.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/HStringArrayMarshaller.cs new file mode 100644 index 000000000..14a06083d --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/HStringArrayMarshaller.cs @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of the Windows Runtime HSTRING type. +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class HStringArrayMarshaller +{ + /// + public static void ConvertToUnmanaged(ReadOnlySpan source, out uint size, out void** array) + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + void** destination = (void**)Marshal.AllocCoTaskMem(sizeof(void*) * source.Length); + + int i = 0; + + try + { + // Marshal all input 'string'-s with 'HStringMarshaller' (note that 'HSTRING' is not a COM object) + for (; i < source.Length; i++) + { + destination[i] = HStringMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // Make sure to release all marshalled objects so far (this shouldn't ever throw) + for (int j = 0; j < i; j++) + { + HStringMarshaller.Free(destination[j]); + } + + // Also release the allocated array to avoid leaking + Marshal.FreeCoTaskMem((nint)destination); + + throw; + } + + size = (uint)source.Length; + array = destination; + } + + /// + public static string[] ConvertToManaged(uint size, void** value) + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + string[] array = new string[(int)size]; + + for (int i = 0; i < size; i++) + { + array[i] = HStringMarshaller.ConvertToManaged(value[i]); + } + + return array; + } + + /// + public static void CopyToUnmanaged(ReadOnlySpan source, uint size, void** destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + int i = 0; + + try + { + // Marshal the items in the input span + for (; i < source.Length; i++) + { + destination[i] = HStringMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // Release resources for any items, if we failed + for (int j = 0; j < i; j++) + { + HStringMarshaller.Free(destination[j]); + } + + throw; + } + } + + /// + public static void CopyToManaged(uint size, void** source, Span destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + for (uint i = 0; i < size; i++) + { + destination[(int)i] = HStringMarshaller.ConvertToManaged(source[i]); + } + } + + /// + public static void Free(uint size, void** array) + { + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(array); + + for (uint i = 0; i < size; i++) + { + HStringMarshaller.Free(array[i]); + } + + Marshal.FreeCoTaskMem((nint)array); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller{TKey, TValue}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller{TKey, TValue}.cs new file mode 100644 index 000000000..2c6d04021 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller{TKey, TValue}.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// An interface for marshalling implementations to support . +/// +/// The type of the key. +/// The type of the value. +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public unsafe interface IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller +{ + /// + /// Marshals a type to its native Windows Runtime representation. + /// + /// The input value to marshal. + /// The marshalled native value. + static abstract WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(KeyValuePair value); + + /// + /// Marshals a native Windows Runtime type to its managed representation. + /// + /// The input value to marshal. + /// The marshalled managed value. + static abstract KeyValuePair ConvertToManaged(void* value); +} diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeManagedValueTypeArrayElementMarshaller{T, TAbi}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeManagedValueTypeArrayElementMarshaller{T, TAbi}.cs new file mode 100644 index 000000000..1f2052b0a --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeManagedValueTypeArrayElementMarshaller{T, TAbi}.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// An interface for marshalling implementations to support . +/// +/// The type of elements in the array. +/// The ABI type for type . +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public interface IWindowsRuntimeManagedValueTypeArrayElementMarshaller + where T : struct + where TAbi : unmanaged +{ + /// + /// Marshals an unmanaged Windows Runtime value type to its native representation. + /// + /// The input value to marshal. + /// The marshalled native value. + static abstract TAbi ConvertToUnmanaged(T value); + + /// + /// Marshals a native Windows Runtime value type to its managed representation. + /// + /// The input value to marshal. + /// The marshalled managed value. + static abstract T ConvertToManaged(TAbi value); + + /// + /// Disposes resources associated with an unmanaged value. + /// + /// The unmanaged value to dispose. + static abstract void Dispose(TAbi value); +} diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeReferenceTypeArrayElementMarshaller{T}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeReferenceTypeArrayElementMarshaller{T}.cs new file mode 100644 index 000000000..bd913731f --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeReferenceTypeArrayElementMarshaller{T}.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// An interface for marshalling implementations to support . +/// +/// The type of elements in the array. +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public unsafe interface IWindowsRuntimeReferenceTypeArrayElementMarshaller + where T : class +{ + /// + /// Marshals a Windows Runtime object to a instance. + /// + /// The input object to marshal. + /// A instance for . + static abstract WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(T? value); + + /// + /// Converts an unmanaged pointer to a Windows Runtime object to a managed object. + /// + /// The input object to convert to managed. + /// The resulting managed object. + static abstract T? ConvertToManaged(void* value); +} diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller{T, TAbi}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller{T, TAbi}.cs new file mode 100644 index 000000000..11743faf1 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller{T, TAbi}.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// An interface for marshalling implementations to support . +/// +/// The type of elements in the array. +/// The ABI type for type . +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public interface IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller + where T : unmanaged + where TAbi : unmanaged +{ + /// + /// Marshals an unmanaged Windows Runtime value type to its native representation. + /// + /// The input value to marshal. + /// The marshalled native value. + static abstract TAbi ConvertToUnmanaged(T value); + + /// + /// Marshals a native Windows Runtime value type to its managed representation. + /// + /// The input value to marshal. + /// The marshalled managed value. + static abstract T ConvertToManaged(TAbi value); +} diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/TypeArrayMarshaller.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/TypeArrayMarshaller.cs new file mode 100644 index 000000000..b68e117da --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/TypeArrayMarshaller.cs @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of the Windows Runtime type. +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class TypeArrayMarshaller +{ + /// + public static void ConvertToUnmanaged(ReadOnlySpan source, out uint size, out ABI.System.Type* array) + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + ABI.System.Type* destination = (ABI.System.Type*)Marshal.AllocCoTaskMem(sizeof(ABI.System.Type) * source.Length); + + int i = 0; + + try + { + // Marshal all input 'Type' objects with its marshaller (note the ABI type will be a value type) + for (; i < source.Length; i++) + { + destination[i] = ABI.System.TypeMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // Dispose each ABI value (it contains an 'HSTRING' which we should release) + for (int j = 0; j < i; j++) + { + ABI.System.TypeMarshaller.Dispose(destination[j]); + } + + // Also release the allocated array to avoid leaking + Marshal.FreeCoTaskMem((nint)destination); + + throw; + } + + size = (uint)source.Length; + array = destination; + } + + /// + public static Type?[] ConvertToManaged(uint size, ABI.System.Type* value) + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + Type?[] array = new Type[(int)size]; + + for (int i = 0; i < size; i++) + { + array[i] = ABI.System.TypeMarshaller.ConvertToManaged(value[i]); + } + + return array; + } + + /// + public static void CopyToUnmanaged(ReadOnlySpan source, uint size, ABI.System.Type* destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + int i = 0; + + try + { + // Marshal the items in the input span + for (; i < source.Length; i++) + { + destination[i] = ABI.System.TypeMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // Release resources for any items, if we failed + for (int j = 0; j < i; j++) + { + ABI.System.TypeMarshaller.Dispose(destination[j]); + } + + throw; + } + } + + /// + public static void CopyToManaged(uint size, ABI.System.Type* source, Span destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + for (uint i = 0; i < size; i++) + { + destination[(int)i] = ABI.System.TypeMarshaller.ConvertToManaged(source[i]); + } + } + + /// + public static void Free(uint size, ABI.System.Type* array) + { + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(array); + + for (uint i = 0; i < size; i++) + { + ABI.System.TypeMarshaller.Dispose(array[i]); + } + + Marshal.FreeCoTaskMem((nint)array); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeArrayMarshallerHelpers.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeArrayMarshallerHelpers.cs new file mode 100644 index 000000000..f8f75c654 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeArrayMarshallerHelpers.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +#pragma warning disable CA2208 + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A helper for marshaller types for Windows Runtime arrays. +/// +internal static unsafe class WindowsRuntimeArrayMarshallerHelpers +{ + /// + /// Validates that the specified destination span has the required number of elements. + /// + /// The expected number of elements in the destination span. + /// The length of the destination span. + /// Thrown if does not equal . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [StackTraceHidden] + public static void ValidateDestinationSize(uint sourceSize, int destinationSize) + { + if ((uint)destinationSize != sourceSize) + { + [StackTraceHidden] + static void ThrowArgumentException() => throw new ArgumentException("The destination array is too small.", "destination"); + + ThrowArgumentException(); + } + } + + /// + /// Validates that the specified destination span has the required number of elements. + /// + /// The length of the span to validate. + /// The expected number of elements in the destination span. + /// Thrown if does not equal . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [StackTraceHidden] + public static void ValidateDestinationSize(int sourceSize, uint destinationSize) + { + if ((uint)sourceSize != destinationSize) + { + [StackTraceHidden] + static void ThrowArgumentException() => throw new ArgumentException("The destination array is too small.", "destination"); + + ThrowArgumentException(); + } + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeBlittableValueTypeArrayMarshaller{T}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeBlittableValueTypeArrayMarshaller{T}.cs new file mode 100644 index 000000000..bc9610774 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeBlittableValueTypeArrayMarshaller{T}.cs @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of blittable Windows Runtime types. +/// +/// The type of elements in the array. +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class WindowsRuntimeBlittableValueTypeArrayMarshaller + where T : unmanaged +{ + /// + /// Marshals a managed array to an unmanaged Windows Runtime array. + /// + /// The source array. + /// The size of the array. + /// The resulting Windows Runtime array. + public static void ConvertToUnmanaged(ReadOnlySpan source, out uint size, out T* array) + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + size = (uint)source.Length; + array = (T*)Marshal.AllocCoTaskMem(sizeof(T) * source.Length); + + source.CopyTo(new Span(array, source.Length)); + } + + /// + /// Marshals an unmanaged Windows Runtime array to a managed array. + /// + /// The size of the array. + /// The source array. + /// The resulting managed array. + public static T[] ConvertToManaged(uint size, T* value) + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + return new ReadOnlySpan(value, (int)size).ToArray(); + } + + /// + /// Copies items from a managed array to the target unmanaged Windows Runtime array. + /// + /// The source array. + /// The size of the array. + /// The destination array. + public static void CopyToUnmanaged(ReadOnlySpan source, uint size, T* destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + source.CopyTo(new Span(destination, (int)size)); + } + + /// + /// Copies items from an unmanaged Windows Runtime array to the target managed array. + /// + /// The size of the array. + /// The source array. + /// The destination array. + public static void CopyToManaged(uint size, T* source, Span destination) + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + new ReadOnlySpan(source, (int)size).CopyTo(destination); + } + + /// + /// Frees the specified array. + /// + /// The size of the array. + /// The input array. + public static void Free(uint size, T* array) + { + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(array); + + Marshal.FreeCoTaskMem((nint)array); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeKeyValuePairTypeArrayMarshaller{TKey, TValue}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeKeyValuePairTypeArrayMarshaller{TKey, TValue}.cs new file mode 100644 index 000000000..ec3e5089c --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeKeyValuePairTypeArrayMarshaller{TKey, TValue}.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of types. +/// +/// The type of the key. +/// The type of the value. +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class WindowsRuntimeKeyValuePairTypeArrayMarshaller +{ + /// + /// The type of marshaller for each managed array element. + public static void ConvertToUnmanaged(ReadOnlySpan> source, out uint size, out void** array) + where TElementMarshaller : IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + void** destination = (void**)Marshal.AllocCoTaskMem(sizeof(void*) * source.Length); + + int i = 0; + + try + { + // Marshal all array elements (the ABI type for 'KeyValuePair<,>' is just 'void*') + for (; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]).DetachThisPtrUnsafe(); + } + } + catch + { + // Release any allocated native 'IKeyValuePair<,>' values + for (int j = 0; j < i; j++) + { + WindowsRuntimeUnknownMarshaller.Free(destination[j]); + } + + // Also release the allocated array to avoid leaking + Marshal.FreeCoTaskMem((nint)destination); + + throw; + } + + size = (uint)source.Length; + array = destination; + } + + /// + /// The type of marshaller for each managed array element. + public static KeyValuePair[] ConvertToManaged(uint size, void** value) + where TElementMarshaller : IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + KeyValuePair[] array = new KeyValuePair[(int)size]; + + for (int i = 0; i < size; i++) + { + array[i] = TElementMarshaller.ConvertToManaged(value[i]); + } + + return array; + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToUnmanaged(ReadOnlySpan> source, uint size, void** destination) + where TElementMarshaller : IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + int i = 0; + + try + { + // Marshal the items in the input span + for (; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]).DetachThisPtrUnsafe(); + } + } + catch + { + // Release resources for any items, if we failed + for (int j = 0; j < i; j++) + { + WindowsRuntimeUnknownMarshaller.Free(destination[j]); + } + + throw; + } + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToManaged(uint size, void** source, Span> destination) + where TElementMarshaller : IWindowsRuntimeKeyValuePairTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + for (uint i = 0; i < size; i++) + { + destination[(int)i] = TElementMarshaller.ConvertToManaged(source[i]); + } + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeManagedValueTypeArrayMarshaller{T, TAbi}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeManagedValueTypeArrayMarshaller{T, TAbi}.cs new file mode 100644 index 000000000..209127fb6 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeManagedValueTypeArrayMarshaller{T, TAbi}.cs @@ -0,0 +1,164 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of managed Windows Runtime types. +/// +/// The type of elements in the array. +/// The ABI type for type . +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class WindowsRuntimeManagedValueTypeArrayMarshaller + where T : struct + where TAbi : unmanaged +{ + /// + /// The type of marshaller for each managed array element. + public static void ConvertToUnmanaged(ReadOnlySpan source, out uint size, out TAbi* array) + where TElementMarshaller : IWindowsRuntimeManagedValueTypeArrayElementMarshaller + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + TAbi* destination = (TAbi*)Marshal.AllocCoTaskMem(sizeof(T) * source.Length); + + int i = 0; + + try + { + // Marshal all array elements with the provided element marshaller. + // Because the native type contains resources, this might throw. + for (; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // Make sure to release all native resources for marshalled values + for (int j = 0; j < i; j++) + { + TElementMarshaller.Dispose(destination[j]); + } + + // Also release the allocated array to avoid leaking + Marshal.FreeCoTaskMem((nint)destination); + + throw; + } + + size = (uint)source.Length; + array = destination; + } + + /// + /// The type of marshaller for each managed array element. + public static T[] ConvertToManaged(uint size, TAbi* value) + where TElementMarshaller : IWindowsRuntimeManagedValueTypeArrayElementMarshaller + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + T[] array = GC.AllocateUninitializedArray((int)size); + + for (int i = 0; i < size; i++) + { + array[i] = TElementMarshaller.ConvertToManaged(value[i]); + } + + return array; + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToUnmanaged(ReadOnlySpan source, uint size, TAbi* destination) + where TElementMarshaller : IWindowsRuntimeManagedValueTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + int i = 0; + + try + { + // Marshal the items in the input span + for (; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // Release resources for any items, if we failed + for (int j = 0; j < i; j++) + { + TElementMarshaller.Dispose(destination[j]); + } + + throw; + } + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToManaged(uint size, TAbi* source, Span destination) + where TElementMarshaller : IWindowsRuntimeManagedValueTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + for (uint i = 0; i < size; i++) + { + destination[(int)i] = TElementMarshaller.ConvertToManaged(source[i]); + } + } + + /// + /// The type of marshaller for each managed array element. + public static void Free(uint size, TAbi* array) + where TElementMarshaller : IWindowsRuntimeManagedValueTypeArrayElementMarshaller + { + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(array); + + for (int i = 0; i < size; i++) + { + TElementMarshaller.Dispose(array[i]); + } + + Marshal.FreeCoTaskMem((nint)array); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeReferenceTypeArrayMarshaller{T}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeReferenceTypeArrayMarshaller{T}.cs new file mode 100644 index 000000000..0ca314f15 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeReferenceTypeArrayMarshaller{T}.cs @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of reference Windows Runtime types. +/// +/// The type of elements in the array. +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class WindowsRuntimeReferenceTypeArrayMarshaller + where T : class +{ + /// + /// The type of marshaller for each managed array element. + public static void ConvertToUnmanaged(ReadOnlySpan source, out uint size, out void** array) + where TElementMarshaller : IWindowsRuntimeReferenceTypeArrayElementMarshaller + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + void** destination = (void**)Marshal.AllocCoTaskMem(sizeof(void*) * source.Length); + + int i = 0; + + try + { + // Marshal all array elements with the provided element marshaller and detach their native pointers + for (; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]).DetachThisPtrUnsafe(); + } + } + catch + { + // Make sure to release all marshalled objects so far (this shouldn't ever throw) + for (int j = 0; j < i; j++) + { + WindowsRuntimeUnknownMarshaller.Free(destination[j]); + } + + // Also release the allocated array to avoid leaking + Marshal.FreeCoTaskMem((nint)destination); + + throw; + } + + size = (uint)source.Length; + array = destination; + } + + /// + /// The type of marshaller for each managed array element. + public static T?[] ConvertToManaged(uint size, void** value) + where TElementMarshaller : IWindowsRuntimeReferenceTypeArrayElementMarshaller + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + T?[] array = new T[(int)size]; + + for (int i = 0; i < size; i++) + { + array[i] = TElementMarshaller.ConvertToManaged(value[i]); + } + + return array; + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToUnmanaged(ReadOnlySpan source, uint size, void** destination) + where TElementMarshaller : IWindowsRuntimeReferenceTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + int i = 0; + + try + { + // Marshal the items in the input span + for (; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]).DetachThisPtrUnsafe(); + } + } + catch + { + // Release resources for any items, if we failed + for (int j = 0; j < i; j++) + { + WindowsRuntimeUnknownMarshaller.Free(destination[j]); + } + + throw; + } + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToManaged(uint size, void** source, Span destination) + where TElementMarshaller : IWindowsRuntimeReferenceTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + for (uint i = 0; i < size; i++) + { + destination[(int)i] = TElementMarshaller.ConvertToManaged(source[i]); + } + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeUnknownArrayMarshaller.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeUnknownArrayMarshaller.cs new file mode 100644 index 000000000..9ee3ecb2b --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeUnknownArrayMarshaller.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of some Windows Runtime types represented as unknown COM interfaces. +/// +/// +/// This type mirrors , but for arrays. +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class WindowsRuntimeUnknownArrayMarshaller +{ + /// + public static void Free(uint size, void** array) + { + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(array); + + for (uint i = 0; i < size; i++) + { + WindowsRuntimeUnknownMarshaller.Free(array[i]); + } + + Marshal.FreeCoTaskMem((nint)array); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeUnmanagedValueTypeArrayMarshaller{T, TAbi}.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeUnmanagedValueTypeArrayMarshaller{T, TAbi}.cs new file mode 100644 index 000000000..f4d623391 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/SzArrays/WindowsRuntimeUnmanagedValueTypeArrayMarshaller{T, TAbi}.cs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices.Marshalling; + +/// +/// A marshaller for arrays of unmanaged Windows Runtime types. +/// +/// The type of elements in the array. +/// The ABI type for type . +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class WindowsRuntimeUnmanagedValueTypeArrayMarshaller + where T : unmanaged + where TAbi : unmanaged +{ + /// + /// The type of marshaller for each managed array element. + public static void ConvertToUnmanaged(ReadOnlySpan source, out uint size, out TAbi* array) + where TElementMarshaller : IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller + { + if (source.IsEmpty) + { + size = 0; + array = null; + + return; + } + + TAbi* destination = (TAbi*)Marshal.AllocCoTaskMem(sizeof(T) * source.Length); + + try + { + // Marshal all array elements with the provided element marshaller. + // We don't need to guard each call, as the ABI type is unmanaged. + for (int i = 0; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]); + } + } + catch + { + // If marshalling any element failed, release the allocated array to avoid + // leaking. This shouldn't really happen with unmanaged value type, since + // the conversions should be pretty trivial, but leave it just in case. + Marshal.FreeCoTaskMem((nint)destination); + + throw; + } + + size = (uint)source.Length; + array = destination; + } + + /// + /// The type of marshaller for each managed array element. + public static T[] ConvertToManaged(uint size, TAbi* value) + where TElementMarshaller : IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller + { + if (size == 0) + { + return []; + } + + ArgumentNullException.ThrowIfNull(value); + + T[] array = GC.AllocateUninitializedArray((int)size); + + for (int i = 0; i < size; i++) + { + array[i] = TElementMarshaller.ConvertToManaged(value[i]); + } + + return array; + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToUnmanaged(ReadOnlySpan source, uint size, TAbi* destination) + where TElementMarshaller : IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(source.Length, size); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(destination); + + for (int i = 0; i < source.Length; i++) + { + destination[i] = TElementMarshaller.ConvertToUnmanaged(source[i]); + } + } + + /// + /// The type of marshaller for each managed array element. + public static void CopyToManaged(uint size, TAbi* source, Span destination) + where TElementMarshaller : IWindowsRuntimeUnmanagedValueTypeArrayElementMarshaller + { + WindowsRuntimeArrayMarshallerHelpers.ValidateDestinationSize(size, destination.Length); + + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(source); + + for (uint i = 0; i < size; i++) + { + destination[(int)i] = TElementMarshaller.ConvertToManaged(source[i]); + } + } + + /// + public static void Free(uint size, TAbi* array) + { + if (size == 0) + { + return; + } + + ArgumentNullException.ThrowIfNull(array); + + Marshal.FreeCoTaskMem((nint)array); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Marshalling/WindowsRuntimeObjectMarshaller.cs b/src/WinRT.Runtime2/InteropServices/Marshalling/WindowsRuntimeObjectMarshaller.cs index ac9be8284..08c8b115a 100644 --- a/src/WinRT.Runtime2/InteropServices/Marshalling/WindowsRuntimeObjectMarshaller.cs +++ b/src/WinRT.Runtime2/InteropServices/Marshalling/WindowsRuntimeObjectMarshaller.cs @@ -72,7 +72,7 @@ static void ThrowNotSupportedException(object value) /// Converts an unmanaged pointer to a Windows Runtime object to a managed object. /// /// The input object to convert to managed. - /// The resulting managed managed object. + /// The resulting managed object. public static object? ConvertToManaged(void* value) { if (value is null)