Replies: 2 comments
-
Hi @ericsink! Big fan of your work. 😊 A Swift projection sounds neat - that would certainly get me interested in the language - I wonder if Apple would have any interest in such a project. By the way, with Rust we've gone beyond just WinRT and encompass the entire Windows API including traditional Win32 and COM APIs. It really opens up the platform to more languages in a big way. https://github.com/microsoft/windows-rs |
Beta Was this translation helpful? Give feedback.
-
@ericsink - I have thought about the path to that - it is something that I think we will need to resolve for the C++ interop in the first place (and we have some compiler internals doing something like that). I think that we really do want a Swift generic protocol that we can monomorphize for the concrete types that we need that can bridge the C++ type. This should give us something like: public func FlushAsync() throws -> WinRT.Windows.Foundation.IAsyncOperation<bool> @kennykerr - that is something that I am actually thinking about with https://github.com/compnerd/swift-winmd. The idea is to actually cover the full COM API surface (and rely on the C interfaces for the Win32 as much as possible, creating overlays if necessary). That would be "raw" and the SwiftWinRT bindings could sit atop to give the projections for the WinRT types. |
Beta Was this translation helpful? Give feedback.
-
@compnerd Another thing I'd like to ask you about...
In the WinRT C header files, when a constructed generic interface (ie parameterized interface) shows up in, for example, a method parameter, it gets a mangled name like
_FIWhatever_INT32
which isIWhatever<T>
closed withINT32
as its type argument. The header file defines this interface with eachT
replaced withINT32
, which makes sense, because that's the actual ABI involved.There aren't actually that many generic types in WinRT, and there aren't actually that different ways they get used, so the total list of constructed generic types in play isn't that large. The header files basically cope by pre-calculating all the cases. For C, this is basically the only option anyway.
Taking this into the Swift world is tricky. For the moment, the option I have implemented is, for each constructed generic type, I also generate a constructed Swift type. In other words, I'm using the same approach as the C header file, and Swift generics are not involved. I don't have a generic form of
IAsyncOperation<T>
. Instead, I have anIAsyncOperation_1_whatever
for each way that it is used, similar to how this is done in the C header.So, the signature for the
FlushAsync
method inWindows.Storage.Streams.IOutputStream
looks (sadly) like this:but here in the special case of an async function, its Swift async form looks fairly normal:
Anyway, I hope this "pre-specialized generics" idea is a temporary solution.
What I want to do is something like what Rust/WinRT is doing (friendly wave of acknowledgment to @kennykerr). They've got a Rust trait (like a Swift protocol) for converting any WinRT type to an ABI form, as well as a Rust trait for every WinRT type to create a signature (or a fragment thereof) that can be used calculate the IID for the parameterized type (see the
from_signature
fn in the GUID code -- I do plan to swipe this code and port it over). So they can generate a Rust generic form of all the parameterized types in WinRT. It's pretty slick, but Swift does C interop very differently from Rust.My plan here is to try to mimic the Rust/WinRT design, but I don't actually know if Swift can do it or not. So my question: Have you by chance thought this far ahead and figured out what's possible? I don't mind forging ahead and see what happens, but if anybody already knows I'm going to crash and burn, it's you, so I figure I might as well ask. :-)
Beta Was this translation helpful? Give feedback.
All reactions