Skip to content

[API Proposal]: APIs to expose managed objects to COM #83471

Closed
@jkoritzinsky

Description

@jkoritzinsky

Background and motivation

As part of our work to provide a source-generator for COM, we need to provide a mechanism for users to request that code be generated to support passing their types to native code.

API Proposal

namespace System.Runtime.InteropServices.Marshalling;


+ public unsafe interface IComExposedClass
+ {
+     public static abstract ComWrappers.ComInterfaceEntry* ComInterfaceEntries { get; }
+     public static abstract int InterfaceEntriesLength { get; }
+ }

+ public unsafe interface IComExposedDetails
+ {
+     ComWrappers.ComInterfaceEntry* ComInterfaceEntries { get; }
+ 
+     int InterfaceEntriesLength { get; }
+ }

+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed unsafe class ComExposedClassAttribute<T> : Attribute, IComExposedDetails
+     where T : IComExposedClass
+ {
+     public ComWrappers.ComInterfaceEntry* ComInterfaceEntries { get; }
+ 
+     public int InterfaceEntriesLength { get; }
+ }

public interface IIUnknownInterfaceDetailsStrategy
{
+    /// <summary>
+    /// Given a <see cref="RuntimeTypeHandle"/> get the details about the type that are exposed to COM.
+    /// </summary>
+    /// <param name="type">RuntimeTypeHandle instance</param>
+    /// <returns>Details if type is known.</returns>
+    IComExposedDetails? GetComExposedTypeDetails(RuntimeTypeHandle type);
}


+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public sealed class GeneratedComClassAttribute : Attribute
+ {
+ }


- public abstract class StrategyBasedComWrappers : ComWrappers
+ public class StrategyBasedComWrappers : ComWrappers
{
+     protected override sealed System.Runtime.InteropServices.ComWrappers.ComInterfaceEntry* ComputeVtables(object obj, System.Runtime.InteropServices.CreateComInterfaceFlags flags, out int count);
}

API Usage

[GeneratedComInterface]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public partial interface IComInterface1
{
    void Method();
}

[GeneratedComClass]
partial class A : IComInterface1
{
    void IComInterface1.Method()
    {
        Console.WriteLine("--- A.IComInterface1.Method");
    }
}

Examples of how generated code will use these APIs is at https://github.com/AaronRobinsonMSFT/ComObjectRedux/pull/8

Alternative Designs

Alternatively, we considered requiring the user to attribute a ComWrappers-derived type with attributes that point to each class type it should support. This ended up becoming a significantly more expensive design that was less trimmable (both this design and the alternative one are trim-friendly).

Risks

This adds a method to an interface, but we haven't shipped the interface yet.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions