Pitch: A vision for COM Interoperability in Swift

I can try to integrate some of this into the vision document itself. I'm basically taking the position that COM is the ABI - IUnknown + ABI vtable layout/function thunks as a dual view of a type.

Correct on both counts. I thought I put that into the document, but there is no way around the AnyObject requirement as the types must be reference counted.

I was thinking that we could close retroactive conformances for COM protocols, but leave it open for Swift protocols. This is required since we need to maintain identity and the layout of the vtable requires complete information.

BSTR is not reference counted and would need a type wrapper. It must be allocated from a different heap via SysAllocString and released via SysFreeString.

HSTRING is reference counted (WindowsCreateString, WindowsDuplicateString, WindowsDeleteString manage the refcount, and WindowsCreateStringReference lets you create uncounted strings - views to statically backed memory).

Yes, I think that this is a desired part of the design as well. Unless you

  • enable COM interop, it should have no material impact (we will need a couple of minor changes to the runtime adding a couple of small entry points which everyone will pay for)
  • use COM interop, should have no real impact and even then would be limited mostly to additional metadata and an additional runtime library
  • should not impact interoperability of modules built without COM interop
4 Likes

Right, I think that’s basically the level at which it needs to be explained: the operations on IUnknown, the query concept, any standard conventions, and the rules on object management.

1 Like

Part of that description should probably be how this interop layer plans to handle COM aggregate objects.

  • Will as? casts invoke the QueryInterface() of the static type? In other words, is let my obj: any IUnknown = IMyObject(); myObj as? ISomeInterface going to call IUnknown::QueryInterface() or IMyObject::QueryInterface()?
  • How does a COM object authored in Swift correctly implement a COM interface by delegating to another object it owns that already implements that interface? Does the Swift version of the object have to manually forward all methods to the subobject, and is that even a valid way to do COM aggregation?