Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new proposed API to Ancillary.Interop #81063

Merged
merged 26 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
51539a7
Update API's and make minimum changes to build
jtschuster Jan 23, 2023
3113a20
Update src/libraries/System.Runtime.InteropServices/tests/ComInterfac…
jtschuster Jan 24, 2023
0f061fd
PR feedback
jtschuster Jan 24, 2023
e51c0d8
Merge branch 'vtableGenUpdate' of https://github.com/jtschuster/runti…
jtschuster Jan 24, 2023
4b936c7
PR Feedback:
jtschuster Jan 25, 2023
d2cecc6
Update API's and make minimum changes to build
jtschuster Jan 23, 2023
1403ae8
PR feedback
jtschuster Jan 24, 2023
b4205b4
Update src/libraries/System.Runtime.InteropServices/tests/ComInterfac…
jtschuster Jan 24, 2023
046b9d1
PR Feedback:
jtschuster Jan 25, 2023
65012f8
Passing tests - not cleaned; do not review
jtschuster Jan 27, 2023
2cddf1c
Merge branch 'vtableGenUpdate' of https://github.com/jtschuster/runti…
jtschuster Jan 31, 2023
53baeeb
Merge branch 'main' of https://github.com/dotnet/runtime into vtableG…
jtschuster Jan 31, 2023
0d15662
Make unwrapperType optional
jtschuster Jan 31, 2023
f4afef5
Remove unused code, clean up comments, format
jtschuster Jan 31, 2023
1599274
PR Feedback
jtschuster Feb 1, 2023
3bb44a1
Pass unwrapper type through NativeThisInfo
jtschuster Feb 2, 2023
8a4d125
Update src/libraries/System.Runtime.InteropServices/gen/Microsoft.Int…
jtschuster Feb 2, 2023
6d0198a
Update src/libraries/System.Runtime.InteropServices/gen/ComInterfaceG…
jtschuster Feb 2, 2023
e5b10e2
Update src/libraries/System.Runtime.InteropServices/gen/ComInterfaceG…
jtschuster Feb 14, 2023
e4529db
Use traditional namespace blocks
jtschuster Feb 14, 2023
0356350
Add InternalsVisibleTo to Ancillary.Interop for VTableGenerator tests
jtschuster Feb 14, 2023
9be677a
Make UnmanagedObjectUnwrapper internal
jtschuster Feb 14, 2023
b643733
Make types public instead of using InternalsVisibleTo
jtschuster Feb 14, 2023
c4f4cc0
Merge branch 'main' of https://github.com/dotnet/runtime into vtableG…
jtschuster Feb 15, 2023
d63a2da
Build xlf, add WrapperType to context
jtschuster Feb 16, 2023
8cd216a
Update xlf
jtschuster Feb 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ public class Ids
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription)));

public static readonly DiagnosticDescriptor InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute =
new DiagnosticDescriptor(
Ids.InvalidLibraryImportAttributeUsage,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(for later change) We should probably have a different ID for the diagnostics here.

GetResourceString(nameof(SR.InvalidVirtualMethodIndexAttributeUsage)),
GetResourceString(nameof(SR.InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute)),
Category,
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription)));

public static readonly DiagnosticDescriptor InvalidStringMarshallingConfiguration =
new DiagnosticDescriptor(
Ids.InvalidLibraryImportAttributeUsage,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace Microsoft.Interop
{
internal static class InlinedTypes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is just prep for later? I don't see it used yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is unused but may be needed later.

{
/// <summary>
/// Returns the ClassDeclarationSyntax for:
/// <code>
/// public sealed unsafe class ComWrappersUnwrapper : IUnmanagedObjectUnwrapper
/// {
/// public static object GetObjectForUnmanagedWrapper(void* ptr)
/// {
/// return ComWrappers.ComInterfaceDispatch.GetInstance<object>((ComWrappers.ComInterfaceDispatch*)ptr);
/// }
/// }
/// </code>
/// </summary>
public static ClassDeclarationSyntax ComWrappersUnwrapper { get; }

public static ClassDeclarationSyntax GetComWrappersUnwrapper()
{
return ClassDeclaration("ComWrappersUnwrapper")
.AddModifiers(Token(SyntaxKind.SealedKeyword),
Token(SyntaxKind.UnsafeKeyword),
Token(SyntaxKind.StaticKeyword),
Token(SyntaxKind.FileKeyword))
.AddMembers(
MethodDeclaration(
PredefinedType(Token(SyntaxKind.ObjectKeyword)),
Identifier("GetComObjectForUnmanagedWrapper"))
.AddModifiers(Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("ptr"))
.WithType(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword)))))
.WithBody(body: Body()));

static BlockSyntax Body()
{
var invocation = InvocationExpression(
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("ComWrappers"),
IdentifierName("ComInterfaceDispatch")),
GenericName(
Identifier("GetInstance"),
TypeArgumentList(
SeparatedList<SyntaxNode>(
new[] { PredefinedType(Token(SyntaxKind.ObjectKeyword)) })))))
.AddArgumentListArguments(
Argument(
null,
Token(SyntaxKind.None),
CastExpression(
PointerType(
QualifiedName(
IdentifierName("ComWrappers"),
IdentifierName("ComInterfaceDispatch"))),
IdentifierName("ptr"))));

return Block(ReturnStatement(invocation));
}
}

/// <summary>
/// <code>
/// file static class UnmanagedObjectUnwrapper
/// {
/// public static object GetObjectForUnmanagedWrapper<T>(void* ptr) where T : IUnmanagedObjectUnwrapper
/// {
/// return T.GetObjectForUnmanagedWrapper(ptr);
/// }
/// }
/// </code>
/// </summary>
public static ClassDeclarationSyntax UnmanagedObjectUnwrapper { get; } = GetUnmanagedObjectUnwrapper();

private static ClassDeclarationSyntax GetUnmanagedObjectUnwrapper()
{
const string tUnwrapper = "TUnwrapper";
return ClassDeclaration("UnmanagedObjectUnwrapper")
.AddModifiers(Token(SyntaxKind.FileKeyword),
Token(SyntaxKind.StaticKeyword))
.AddMembers(
MethodDeclaration(
PredefinedType(Token(SyntaxKind.ObjectKeyword)),
Identifier("GetObjectForUnmanagedWrapper"))
.AddModifiers(Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.StaticKeyword))
.AddTypeParameterListParameters(
TypeParameter(Identifier(tUnwrapper)))
.AddParameterListParameters(
Parameter(Identifier("ptr"))
.WithType(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword)))))
.AddConstraintClauses(TypeParameterConstraintClause(IdentifierName(tUnwrapper))
.AddConstraints(TypeConstraint(ParseTypeName(TypeNames.IUnmanagedObjectUnwrapper))))
.WithBody(body: Body()));

static BlockSyntax Body()
{
var invocation = InvocationExpression(
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("T"),
IdentifierName("GetObjectForUnmanagedWrapper")))
.AddArgumentListArguments(
Argument(
null,
Token(SyntaxKind.None),
IdentifierName("ptr")));

return Block(ReturnStatement(invocation));
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public ManagedToNativeVTableMethodGenerator(
if (implicitThis)
{
ImmutableArray<TypePositionInfo>.Builder newArgTypes = ImmutableArray.CreateBuilder<TypePositionInfo>(argTypes.Length + 1);
newArgTypes.Add(new TypePositionInfo(SpecialTypeInfo.IntPtr, NoMarshallingInfo.Instance)
newArgTypes.Add(new TypePositionInfo(new PointerTypeInfo("void*", "void*", false), NoMarshallingInfo.Instance)
{
InstanceIdentifier = NativeThisParameterIdentifier,
NativeIndex = 0
Expand Down Expand Up @@ -101,7 +101,7 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray<FunctionPointerUnm
{
var setupStatements = new List<StatementSyntax>
{
// var (<thisParameter>, <virtualMethodTable>) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<<containingTypeName>>();
// var (<thisParameter>, <virtualMethodTable>) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(typeof(<containingTypeName>));
ExpressionStatement(
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
Expand All @@ -121,12 +121,9 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray<FunctionPointerUnm
CastExpression(
ParseTypeName(TypeNames.IUnmanagedVirtualMethodTableProvider),
ThisExpression())),
GenericName(
Identifier("GetVirtualMethodTableInfoForKey"),
TypeArgumentList(
SingletonSeparatedList(containingTypeName)))))
IdentifierName("GetVirtualMethodTableInfoForKey") ))
.WithArgumentList(
ArgumentList())))
ArgumentList(SeparatedList(new[]{ Argument(TypeOfExpression(containingTypeName)) })))))
};

GeneratedStatements statements = GeneratedStatements.Create(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace Microsoft.Interop
{
internal sealed record NativeThisInfo : MarshallingInfo
{
public static readonly NativeThisInfo Instance = new();
}
internal sealed record NativeThisInfo(TypeSyntax UnwrapperType) : MarshallingInfo;

internal sealed class NativeToManagedThisMarshallerFactory : IMarshallingGeneratorFactory
{
Expand All @@ -30,27 +28,34 @@ private sealed class Marshaller : IMarshallingGenerator
public ManagedTypeInfo AsNativeType(TypePositionInfo info) => new PointerTypeInfo("void*", "void*", false);
public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context)
{
Debug.Assert(info.MarshallingAttributeInfo is NativeThisInfo);
TypeSyntax unwrapperType = ((NativeThisInfo)info.MarshallingAttributeInfo).UnwrapperType;
if (context.CurrentStage != StubCodeContext.Stage.Unmarshal)
{
yield break;
}

(string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);

// <managed> = IUnmanagedVirtualMethodTableProvider.GetObjectForUnmanagedWrapper<<managedType>>(<native>);
// <managed> = (<managedType>)UnmanagedObjectUnwrapper.GetObjectFormUnmanagedWrapper<TUnmanagedUnwrapper>(<native>);
yield return ExpressionStatement(
AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
IdentifierName(managedIdentifier),
InvocationExpression(
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
ParseTypeName(TypeNames.IUnmanagedVirtualMethodTableProvider),
GenericName(Identifier("GetObjectForUnmanagedWrapper"),
TypeArgumentList(
SingletonSeparatedList(
info.ManagedType.Syntax)))),
ArgumentList(
SingletonSeparatedList(
Argument(IdentifierName(nativeIdentifier)))))));
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
IdentifierName(managedIdentifier),
CastExpression(
info.ManagedType.Syntax,
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
ParseTypeName(TypeNames.UnmanagedObjectUnwrapper),
GenericName(Identifier("GetObjectForUnmanagedWrapper"))
.WithTypeArgumentList(
TypeArgumentList(
SingletonSeparatedList(
unwrapperType)))),
ArgumentList(
SingletonSeparatedList(
Argument(IdentifierName(nativeIdentifier))))))));
}

public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.NativeType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,7 @@
<data name="InterfaceTypeNotSupportedMessage" xml:space="preserve">
<value>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</value>
</data>
<data name="InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute" xml:space="preserve">
<value>Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </value>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: single quote around type names

</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Metoda {0} je obsažena v typu {1}, který není označen jako „partial“. Generování zdrojů volání P/Invoke bude metodu {0} ignorovat.</target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute">
<source>Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </source>
<target state="new">Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodDescription">
<source>Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic.</source>
<target state="translated">Metody označené atributem LibraryImportAttribute by měly být typu „static“, „partial“ a non-generic. Generování zdrojů volání P/Invoke bude ignorovat metody typu non-„static“, non-„partial“ a generic.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Die Methode \"{0}\" ist in einem Typ \"{1}\" enthalten, der nicht als \"partiell\" gekennzeichnet ist. Die P/Invoke-Quellgenerierung ignoriert die Methode \"{0}\".</target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute">
<source>Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </source>
<target state="new">Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodDescription">
<source>Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic.</source>
<target state="translated">Methoden, die mit \"LibraryImportAttribute\" gekennzeichnet sind, sollten \"statisch\", \"partiell\" und nicht generisch sein. Die P/Invoke-Quellgenerierung ignoriert Methoden, die nicht \"statisch\", nicht \"partiell\" oder generisch sind.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<target state="translated">El método “{0}” está contenido en un tipo “{1}” que no está marcado como “partial”. La generación de código fuente P/Invoke omitirá el método “{0}”.</target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute">
<source>Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </source>
<target state="new">Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodDescription">
<source>Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic.</source>
<target state="translated">Los métodos marcados con “LibraryImportAttribute” deben ser “static”, “partial” y no genéricos. La generación de código fuente P/Invoke omitirá los métodos que no sean “static”, “partial” ni genéricos.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<target state="translated">La méthode « {0} » est contenue dans un type « {1} » qui n’est pas marqué comme étant « partial ». La génération source P/Invoke ignore la méthode « {0} ».</target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute">
<source>Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </source>
<target state="new">Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodDescription">
<source>Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic.</source>
<target state="translated">Les méthodes marquées avec « LibraryImportAttribute » doivent être « static », « partial » et non génériques. La génération de source P/Invoke ignore les méthodes qui ne sont pas statiques, non partielles ou génériques.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
<target state="translated">Il metodo '{0}' è contenuto in un tipo '{1}' non contrassegnato come 'partial'. Durante la generazione dell'origine P/Invoke il metodo '{0}' verrà ignorato.</target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute">
<source>Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </source>
<target state="new">Containing type of method with VirtualMethodIndexAttribute does not have a UnmanagedObjectUnwrapperAttribute. </target>
<note />
</trans-unit>
<trans-unit id="InvalidAttributedMethodDescription">
<source>Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic.</source>
<target state="translated">I metodi contrassegnati con 'LibraryImportAttribute' devono essere 'static', 'partial' e non generici. Durante la generazione dell'origine P/Invoke i metodi non 'static', non 'partial' o generici verranno ignorati.</target>
Expand Down
Loading