-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
[API Proposal]: Define parameter marshalling of interfaces #85797
Comments
Tagging subscribers to this area: @dotnet/interop-contrib Issue DetailsBackground and motivationToday, we allow developers to specify the default marshaller for a type in source-generated marshalling with the When API Proposalnamespace System.Runtime.InteropServices.Marshalling;
- [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Delegate)]
+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate)]
public sealed class NativeMarshallingAttribute : Attribute
{
} API Usage[NativeMarshalling(typeof(Marshaller))]
interface IMyComInterface
{} Alternative DesignsNone RisksN/A
|
We might want to add in a built-in marshaller type too. public static class ComInterfaceMarshaller<T>
{
private static StrategyBasedComWrappers s_wrappers = new();
public static void* ConvertToUnmanaged(T managed);
public static T ConvertToManaged(void* unmanaged);
}
// Perhaps nice to have?
public static class ComInterfaceMarshaller<T, U> where U : ComWrappers
{
private static U s_wrappers = new();
public static void* ConvertToUnmanaged(T managed);
public static T ConvertToManaged(void* unmanaged);
} |
How would this integrate with [LibraryImport("Ole32")]
private static partial int CreateStreamOnHGlobal(
void* hGlobal,
bool fDeleteOnRelease,
out IStream ppstm);
[NativeMarshalling(typeof(Marshaller))]
private interface IStream
{ } Do we have any concerns with down level support if the above is true? The |
For LibraryImport, these marshallers would work like any other user-defined marshaller. They don't work downlevel below .NET 7. If we decide to make the |
namespace System.Runtime.InteropServices.Marshalling;
- [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Delegate)]
+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate)]
public sealed class NativeMarshallingAttribute : Attribute
{
} namespace System.Runtime.InteropServices.Marshalling;
/// <summary>
/// COM interface marshaller using a StrategyBasedComWrappers instance
/// </summary>
/// <remarks>
/// This marshaller will always pass the <see cref="CreateObjectFlags.Unwrap"/> flag
/// to <see cref="ComWrappers.GetOrCreateObjectForComInstance(IntPtr, CreateObjectFlags)"/>.
/// </remarks>
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder), MarshalMode.Default, typeof(ComInterfaceMarshaller<>))]
public static class ComInterfaceMarshaller<T>
{
public static void* ConvertToUnmanaged(T managed);
public static T ConvertToManaged(void* unmanaged);
}
/// <summary>
/// COM interface marshaller using a StrategyBasedComWrappers instance
/// that will only create unique native object wrappers (RCW).
/// </summary>
/// <remarks>
/// This marshaller will always pass the <see cref="CreateObjectFlags.Unwrap"/> and <see cref="CreateObjectFlags.UniqueInstance"/> flags
/// to <see cref="ComWrappers.GetOrCreateObjectForComInstance(IntPtr, CreateObjectFlags)"/>.
/// </remarks>
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder), MarshalMode.Default, typeof(UniqueComInterfaceMarshaller<>))]
public static class UniqueComInterfaceMarshaller<T>
{
public static void* ConvertToUnmanaged(T managed);
public static T ConvertToManaged(void* unmanaged);
} |
Background and motivation
Today, we allow developers to specify the default marshaller for a type in source-generated marshalling with the
NativeMarshalling
attribute. We should allow this attribute on interface types, so interface types in source-generated interop signatures can have default marshallers. This wasn't common before, but with source-generated COM coming into the mix, this scenario is much more popular.When
NativeMarshalling
is applied to an interface, the source-generator will only respect it when the static type in a signature is the interface type (same rules we use for all other types). We don't do any inheritance walking, we only look on the type itself.API Proposal
API Usage
Alternative Designs
None
Risks
This proposal does not attempt to provide first-class support for more complicated scenarios such as using a specific
ComWrappers
instance or specifying the IID of an object in a method signature. Rather than add complexity to the source generator, users can handle such scenarios manually by explicitly marshalling using theirComWrappers
instance and/or defining different interfaces.The text was updated successfully, but these errors were encountered: