Since we have Swift-java now, wouldn't it be a good idea to have Swift-dotnet as well? Are there any plans to do it?
The advantages are similar to to the ones of having java interop (access to huge ecosystem), while on it might be easier to than JVM - since C# and Swift are somewhat closer semantically than Java and Swift.
In addition, a good interop (or even a version that targets dotnet) could make application level development for Windows (despite dotnet being open source and cross platform), and hence adoption of the language a easier - after all, unfortunately, Windows experience of Swift development is still not the best - which is a deal blocker for teaching Swift, or adopting it in education programs much harder - outside of US (most people don't own Apple machines, as they are not really affordable and non-Apple machines in 99% of cases come with Windows preinstalled).
While I'm not entirely up to date how far along it is, but .NET has gained some calling convention support AFAIR?
- Proposal: designs/proposed/swift-interop.md at main · dotnet/designs · GitHub
- Implementation Runtime support for Swift Interop in .NET 9 · Issue #93631 · dotnet/runtime · GitHub - which is part of .NET 9 it seems (?)
As well as this work done by Xamarin:
So in some ways this is more support the .net platform provides to Swift than current day JDK which doesn't support Swift's calling convention.
If you'd like to help those efforts I'm sure the .NET folks would be able to point at what might need more work etc
After following the conversations on the .NET side a bit:
- It seems like .NET 9 had preliminary work done
- This was followed in .NET 10 and they have an experimental POC
- It's meant for internal products like MAUI so they're only supporting features used by specific targeted frameworks
It's one way interop (.NET calls into Swift)It's complicated- It'll work on Apple platforms only
So far they seem to have added a few runtime capabilities to support the calling convention and there seems to be experimental projection tooling (to generate C# bindings to call into Swift).
The runtime, tooling and documentation is in this repo.
They have a sample MacCatalyst app built with it.
Here's a copy of relevant details from the README for posterity.
Usage
The tooling can consume a Swift ABI file or a framework name from the standard library. If a framework name is provided, the tool generates the ABI file based on the .swiftinterface
file. This ABI file contains a JSON representation of the abstract syntax tree of the .swiftinterface
file. Multiple Swift ABI files and frameworks can be specified for bindings.
Description:
Swift bindings generator.
Usage:
SwiftBindings [options]
Options:
-a, --swiftabi Required. Path to the Swift ABI file.
-d, --dylib Required. Path to the dynamic library.
-t, --tbd Required. Path to the TBD file.
-o, --output Required. Output directory for generated bindings.
-v, --verbose Verbosity level. 0 = No logging, 1 = General information, 2 = Debugging information. (default: 1)
Supported scenarios
StoreKit in-app purchase example:
SwiftArray<SwiftString> productIdentifiers = new SwiftArray<SwiftString>();
productIdentifiers.Append(new SwiftString("id1"));
productIdentifiers.Append(new SwiftString("id2"));
Task<SwiftArray<SwiftString>> productsTask = Product.products<SwiftArray<SwiftString>>(productIdentifiers);
SwiftArray<Product> products = await productsTask;
Product product = products[0];
await product.purchase(new SwiftSet<Product.PurchaseOption>());
A complete list of supported scenarios is available in src/Swift.Bindings/tests
.
If an unsupported syntax element is encountered in the ABI file, the tooling will ignore it and generate C# source code for known syntax elements. The generated C# bindings are published as source files to the output directory, allowing users to modify them before compilation.
Experimental packages
NuGet feed: https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-experimental
StoreKit bindings:
Swift.Bindings.MacOSX.Experimental -version 1.0.0-alpha.25201.1
Swift.Bindings.MacCatalyst.Experimental -version 1.0.0-alpha.25201.1
Swift.Bindings.iPhoneSimulator.Experimental -version 1.0.0-alpha.25201.1
Swift.Bindings.iPhoneOS.Experimental -version 1.0.0-alpha.25201.1
Swift.Bindings.AppleTVSimulator.Experimental -version 1.0.0-alpha.25201.1
Swift.Bindings.AppleTVOS.Experimental -version 1.0.0-alpha.25201.1
Projection tooling:
Swift.Bindings -version 1.0.0-alpha.25201.1
Tried this one?
There's also this made by @ericsink .
It would let you do
import dotnet;
import aspnetcore;
typealias WebApplication = Microsoft.AspNetCore.Builder.WebApplication;
typealias Func = System.Func_1;
public func swift_main() throws -> Swift.Int32 {
let app = try WebApplication.Create()
try app.MapGet(
pattern: "/",
handler:
Func<System.String>
{
() -> System.String in
"Hello World!"
}
);
try app.Run();
return 0;
}
I can't get it to run on newer swift or dotnet but it did evidently work at one point.