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

Implement unmanaged-to-managed direction for vtable stub generator #77130

Merged
merged 24 commits into from
Dec 8, 2022

Conversation

jkoritzinsky
Copy link
Member

@jkoritzinsky jkoritzinsky commented Oct 17, 2022

Implement the unmanaged-to-managed direction for stubs generated with the VTableIndexStubGenerator.

This PR also includes a design doc for how to handle exception handling at the unmanaged-to-managed boundary, which this PR implements.

Generated Code (NativeToManagedStubs.g.cs)
// <auto-generated/>
namespace ComInterfaceGenerator.Tests
{
    internal unsafe partial class NativeExportsNE
    {
        internal unsafe partial class ImplicitThis
        {
            internal unsafe partial interface INativeObject
            {
                internal unsafe partial interface Native
                {
                    [System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute]
                    internal static int ABI_GetData(void* __this_native)
                    {
                        global::ComInterfaceGenerator.Tests.NativeExportsNE.ImplicitThis.INativeObject @this;
                        int __retVal = default;
                        // Unmarshal - Convert native data to managed data.
                        @this = System.Runtime.InteropServices.IUnmanagedVirtualMethodTableProvider<byte>.GetObjectForUnmanagedWrapper<global::ComInterfaceGenerator.Tests.NativeExportsNE.ImplicitThis.INativeObject>(__this_native);
                        __retVal = @this.GetData();
                        return __retVal;
                    }
                }
            }
        }
    }
}
namespace ComInterfaceGenerator.Tests
{
    internal unsafe partial class NativeExportsNE
    {
        internal unsafe partial class ImplicitThis
        {
            internal unsafe partial interface INativeObject
            {
                internal unsafe partial interface Native
                {
                    [System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute]
                    internal static void ABI_SetData(void* __this_native, int x)
                    {
                        global::ComInterfaceGenerator.Tests.NativeExportsNE.ImplicitThis.INativeObject @this;
                        // Unmarshal - Convert native data to managed data.
                        @this = System.Runtime.InteropServices.IUnmanagedVirtualMethodTableProvider<byte>.GetObjectForUnmanagedWrapper<global::ComInterfaceGenerator.Tests.NativeExportsNE.ImplicitThis.INativeObject>(__this_native);
                        @this.SetData(x);
                    }
                }
            }
        }
    }
}
Generated code (PopulateVTable.g.cs)
// <auto-generated/>
namespace ComInterfaceGenerator.Tests
{
    internal unsafe partial class NativeExportsNE
    {
        internal unsafe partial class ImplicitThis
        {
            internal unsafe partial interface INativeObject
            {
                internal unsafe partial interface Native
                {
                    internal static void PopulateUnmanagedVirtualMethodTable(System.Span<nint> vtable)
                    {
                        vtable[0] = (nint)(delegate* unmanaged<void*, int> )&ABI_GetData;
                        vtable[1] = (nint)(delegate* unmanaged<void*, int, void> )&ABI_SetData;
                    }
                }
            }
        }
    }
}

@jkoritzinsky jkoritzinsky added area-System.Runtime.InteropServices source-generator Indicates an issue with a source generator feature labels Oct 17, 2022
@ghost ghost assigned jkoritzinsky Oct 17, 2022
@ghost
Copy link

ghost commented Oct 17, 2022

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

Issue Details

Implement the unmanaged-to-managed direction for stubs generated with the VTableIndexStubGenerator.

This PR also includes a design doc for how to handle exception handling at the unmanaged-to-managed boundary, which this PR will also implement.

TODO:

  • Update custom marshalling model to work in the reverse direction.
  • Update any other hard-coded marshallers that need to support the reverse direction.
  • Implement the EH interop spec as specified in this PR.
Author: jkoritzinsky
Assignees: -
Labels:

area-System.Runtime.InteropServices, source-generator

Milestone: -

Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

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

Can you share an example of what the generated source looks like?

@jkoritzinsky
Copy link
Member Author

Once I've done more work and gotten this PR to at least some semblance of green, I'll add some example generated code to the top of this PR.

…rect types and the unmanaged/native names for the parameters.
…other (commented out for now) case that we need to fix.
… and not a TypeSyntax. We need to reason about this type for the unmanaged exception handling design, so using a ManagedTypeInfo is preferable.
…ether we're marshalling a parameter/return value/etc from managed to unmanaged or vice versa. This abstraction will be useful when enabling unmanaged->managed stubs as we won't need to go update every marshalling generator to correctly understand what to do.

Also rename some members from "in/out/ref" to use the direction-based names.
@jkoritzinsky
Copy link
Member Author

I've pushed all of the changes to this PR, but I'm going to spin off some of these commits into separate PRs to make them more reviewable. I'll mark this as ready for review once those PRs are merged.

@jkoritzinsky jkoritzinsky marked this pull request as ready for review November 21, 2022 18:33
Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

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

Please give @elinor-fung a chance to review this, but I am good.

@jkoritzinsky
Copy link
Member Author

All test failures are unrelated. @elinor-fung any more feedback before I merge this?

Copy link
Member

@elinor-fung elinor-fung left a comment

Choose a reason for hiding this comment

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

I think it would still be helpful to put examples of the generated source in the PR description. Beyond the PR itself, I have found it helpful when looking through previous changes when reworking (or breaking) things when we were working on LibraryImport.

I think we also need tests that would have caught the exception marshalling wiring (fine with that in a separate change) .

@jkoritzinsky
Copy link
Member Author

I'll add the runtime tests for ExceptionMarshalling in a separate change.

…nMarshalling explicitly to Custom to match the design for StringMarshalling
Copy link
Member

@elinor-fung elinor-fung left a comment

Choose a reason for hiding this comment

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

Thanks for adding those generated code examples!

@jkoritzinsky
Copy link
Member Author

Failure is unrelated.

@jkoritzinsky jkoritzinsky merged commit 1ca6a6f into dotnet:main Dec 8, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Jan 7, 2023
@jkoritzinsky jkoritzinsky deleted the vtable-unmanged-to-managed branch March 22, 2024 01:25
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Runtime.InteropServices source-generator Indicates an issue with a source generator feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants