-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Fix NativeMarshalling attribute override for COM interfaces #121643
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
base: main
Are you sure you want to change the base?
Conversation
Modified ComInterfaceMarshallingInfoProvider to check for NativeMarshallingAttribute on COM interfaces and defer to that parser when present. Added tests to verify the fix works for both ComInterfaceGenerator and LibraryImportGenerator. Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
|
@copilot you need to add behavioral tests to ComInterfaceGenerator.Tests.csproj. Add a test that gets the same ComInterface instance from a LibraryImportMethod twice and validate that they are not the same instance. Also add a method on the interface that returns a COM interface. The implementation should return 'this'. In the test, validate that the returned instance is a new object, not the same cached instance. |
Added tests to ComInterfaceGenerator.Tests that verify: 1. Getting the same COM interface twice returns unique instances when using NativeMarshallingAttribute with UniqueComInterfaceMarshaller 2. COM interface methods returning the same interface type return new managed instances, not cached ones Created IUniqueMarshalling interface with NativeMarshallingAttribute, native exports, and comprehensive tests. Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Added behavioral tests in commit 3d67609. The tests verify:
Created IUniqueMarshalling interface with |
|
@copilot You should be able to use StrategyBasedComWrappers in UniqueMarshalling.CreateComObject without having to create a new ComWrappers implementation. Delete MyComWrapper and use StrategyBasedComWrappers instead. Create a SharedTypes.ComInterfaces.UniqueMarshalling instance instead of ImplementingObject. |
Removed custom MyComWrapper implementation and ImplementingObject class. Now using StrategyBasedComWrappers directly with SharedTypes.ComInterfaces.UniqueMarshalling instance, which leverages the GeneratedComClass attribute to handle the COM vtable automatically. Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Simplified in commit 1a37329. Removed MyComWrapper and ImplementingObject classes. Now using StrategyBasedComWrappers directly with SharedTypes.ComInterfaces.UniqueMarshalling instance, which uses the GeneratedComClass attribute to automatically handle the COM vtable. |
…parser order, not arbitrary attribute order.
...me.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/UniqueMarshalling.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a bug where the [NativeMarshalling(typeof(CustomMarshaller<T>))] attribute on COM interfaces was being ignored in favor of the default ComInterfaceMarshaller<T>. The fix enables consumers to specify custom marshallers (e.g., UniqueComInterfaceMarshaller<T> for unique RCW instances) on COM interfaces.
Key Changes
-
Parser Priority Fix: Modified
MarshallingInfoParser.csto iterate parsers before attributes inGetMarshallingInfoForAttributes, ensuringNativeMarshallingAttributeParser(which appears beforeComInterfaceMarshallingInfoProviderin the parser list) handles[NativeMarshalling]attributes before the default COM interface marshaller. -
Comprehensive Test Coverage: Added unit tests for compilation validation in both ComInterfaceGenerator and LibraryImportGenerator test projects, plus end-to-end behavioral tests verifying unique RCW instance creation.
-
Test Infrastructure: Simplified native export implementation using
StrategyBasedComWrappersandGeneratedComClassinstead of manual COM vtable management.
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| MarshallingInfoParser.cs | Refactored attribute parsing to prioritize parsers over attributes, enabling NativeMarshallingAttributeParser to handle custom marshallers before ComInterfaceMarshallingInfoProvider |
| CodeSnippets.cs (ComInterfaceGenerator.Unit.Tests) | Added unit test snippet for COM interface with NativeMarshalling attribute |
| Compiles.cs (ComInterfaceGenerator.Unit.Tests) | Added test case for compilation validation |
| CodeSnippets.cs (LibraryImportGenerator.UnitTests) | Added unit test snippet for COM interface with NativeMarshalling in LibraryImport |
| Compiles.cs (LibraryImportGenerator.UnitTests) | Added test case for compilation validation |
| IUniqueMarshalling.cs | Defined test COM interface with NativeMarshalling attribute and implementation class |
| NativeMarshallingAttributeTests.cs | Added behavioral tests verifying unique RCW instance creation |
| UniqueMarshalling.cs (NativeExports) | Native export function to create COM objects for testing |
...Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NativeMarshallingAttributeTests.cs
Outdated
Show resolved
Hide resolved
Modified UniqueMarshalling.CreateComObject to cache and return the same pointer on every call, ensuring that the same underlying COM object is used. Updated test to verify that while UniqueComInterfaceMarshaller creates different managed instances for each call, they both refer to the same underlying COM object (same cached pointer). Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
...Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NativeMarshallingAttributeTests.cs
Outdated
Show resolved
Hide resolved
Updated comment to clarify that calling NewUniqueMarshalling() twice returns different managed instances for the same COM object, addressing code review feedback. Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Added IUniqueMarshalling.cs as a Compile item in LibraryImportGenerator.Tests.csproj to enable the generator to process the COM interface definition. Moved the GetSameComInterfaceTwiceReturnsUniqueInstances test to LibraryImportGenerator.Tests since it tests LibraryImport marshalling behavior. Kept MethodReturningComInterfaceReturnsUniqueInstance in ComInterfaceGenerator.Tests as it tests COM interface method behavior. Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
|
Tagging subscribers to this area: @dotnet/interop-contrib |
|
@AaronRobinsonMSFT PTAL when you have a chance |
Fix NativeMarshalling attribute override for COM interfaces
Plan
Changes Made
MarshallingInfoParser.cs & ComInterfaceMarshallingInfoProvider.cs: Improved implementation by the maintainer to iterate through parsers in order (NativeMarshallingAttributeParser before ComInterfaceMarshallingInfoProvider) rather than iterating through attributes, ensuring NativeMarshallingAttribute is always checked first.
Unit Tests: Added compilation tests to verify the generators handle NativeMarshalling correctly
Behavioral Tests:
[NativeMarshalling(typeof(UniqueComInterfaceMarshaller<IUniqueMarshalling>))]Test Results
Issue Summary
When a COM interface has both
[GeneratedComInterface]and[NativeMarshalling(typeof(UniqueComInterfaceMarshaller<IFoo>))], the generator should use the custom marshaller specified inNativeMarshallingAttribute. Previously, it always used the defaultComInterfaceMarshaller<T>.The fix ensures that when
NativeMarshallingAttributeis present on a COM interface, it takes precedence over the default marshaller by ensuring the parser order checks NativeMarshallingAttributeParser before ComInterfaceMarshallingInfoProvider.Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.