dotnet / runtimelab

This repo is for experimentation and exploring new ideas that may or may not make it into the main dotnet/runtime repo.
MIT License
1.36k stars 188 forks source link

Review Swift projections tooling UX and functionality #2582

Open kotlarmilos opened 1 month ago

kotlarmilos commented 1 month ago

Overview

This proposal discusses the tooling UX. The primary goal is to simplify the process of generating and managing bindings between Swift and .NET. The ideal scenario is to achieve good tradeoff between rich support and lightweight UI.

Here are the tooling requirements:

Input

Users can specify a Swift code either by framework name or by providing a path to a Swift ABI file. In case of framework, the tool triggers the front-end Swift compiler to generate an ABI file from a swiftinterface. Options:

--framework   Swift framework name.
--abipath     Path to the Swift ABI file.

Examples:

--framework CryptoKit --framework Foundation
--abipath /path/to/swift.abi.json

Filtering

The tooling should allow users to filter types through exclusive options. Filtering can be performed by specifying include or exclude options for the type and function names. Options:

--include [pattern]
--exclude [pattern]

Examples:

--include CryptoKit.ChaChaPoly --include Foundation.Data
--exclude CryptoKit.AES

To improve usability, the tool should recursively resolve dependencies by generating bindings for requested types by utilizing the filtering internally. This should reduce generation time and SOD.

Performance

Layout projections for frozen types should be computed during the binding generation phase to minimize runtime overhead. Layouts for non-frozen types should be lazy loaded; determined during initialization rather than runtime startup.

Unsupported scenarios

In cases where binding generation is not supported, the tool should generate a stub source code with unimplemented types and functions. It should be followed with documentation and common binding scenarios to guide users in manually writing bindings.

Examples:

// Stub file generated for Type1

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Swift;
using Swift.Runtime;
using Swift.Foundation;

namespace Swift.ManualBindings
{

    public class Type1
    {
        // TODO: Implement projections
    }
}

Explicit memory management

Users should have the option to specify which types should implement the IDisposable interface for explicit memory management. Otherwise, for non-frozen types projected as C# classes, memory is allocated on the .NET side and passed to the Swift initializer via the return buffer register. In these cases, the tool should generate finalizers to implicitly invoke deinitializers and release memory. Options:

--idisposable [type name]

Examples:

--idisposable Foundation.Data

Shipping

The final bindings should be distributed as C# source code, which users can inspect and modify. The tool should also support a custom preambles such as licensing information. Options:

--preamble [license text]

Examples:

--preamble "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License."

/cc: @agocke @jkoritzinsky @AaronRobinsonMSFT @stephen-hawley @rolfbjarne @jkotas @dalexsoto