| File: Marshallers\StructAsHResultMarshallerFactory.cs | Web Access |
| Project: src\runtime\src\libraries\System.Runtime.InteropServices\gen\ComInterfaceGenerator\ComInterfaceGenerator.csproj (Microsoft.Interop.ComInterfaceGenerator) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using static Microsoft.Interop.SyntaxFactoryExtensions; namespace Microsoft.Interop { internal sealed class StructAsHResultMarshallerFactory : IMarshallingGeneratorResolver { private static readonly Marshaller s_marshaller = new(); public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) { // Value type with MarshalAs(UnmanagedType.Error), to be marshalled as an unmanaged HRESULT. if (info is { ManagedType: ValueTypeInfo, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.Error, _) }) { return ResolvedGenerator.Resolved(s_marshaller.Bind(info, context)); } return ResolvedGenerator.UnresolvedGenerator; } private sealed class Marshaller : IUnboundMarshallingGenerator { public ManagedTypeInfo AsNativeType(TypePositionInfo info) => SpecialTypeInfo.Int32; public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { var (managed, unmanaged) = context.GetIdentifiers(info); switch (context.CurrentStage) { case StubIdentifierContext.Stage.Marshal: if (MarshallerHelpers.GetMarshalDirection(info, codeContext) is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { // unmanaged = Unsafe.BitCast<managedType, int>(managed); yield return AssignmentStatement( IdentifierName(unmanaged), MethodInvocation( ParseTypeName(TypeNames.System_Runtime_CompilerServices_Unsafe), GenericName(Identifier("BitCast"), TypeArgumentList( SeparatedList(new[] { info.ManagedType.Syntax, AsNativeType(info).Syntax }))), Argument(IdentifierName(managed)))); } break; case StubIdentifierContext.Stage.Unmarshal: if (MarshallerHelpers.GetMarshalDirection(info, codeContext) is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) { // managed = Unsafe.BitCast<int, managedType>(unmanaged); yield return AssignmentStatement( IdentifierName(managed), MethodInvocation( ParseTypeName(TypeNames.System_Runtime_CompilerServices_Unsafe), GenericName(Identifier("BitCast"), TypeArgumentList( SeparatedList(new[] { AsNativeType(info).Syntax, info.ManagedType.Syntax }))), Argument(IdentifierName(unmanaged)))); } break; default: break; } } public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (info.IsByRef) { return ValueBoundaryBehavior.AddressOfNativeIdentifier; } return ValueBoundaryBehavior.NativeIdentifier; } public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; } } }