- 
                Notifications
    You must be signed in to change notification settings 
- Fork 214
Add initial documentation for the projection tooling #2512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Merged
      
      
    
  
     Merged
                    Changes from all commits
      Commits
    
    
            Show all changes
          
          
            11 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      d5ba6ae
              
                Add initial documentation skeleton
              
              
                kotlarmilos 7a80ed8
              
                Update docs/README.md
              
              
                kotlarmilos 1d23cbf
              
                Update docs/README.md
              
              
                kotlarmilos 29a5067
              
                Update primitive types mapping
              
              
                kotlarmilos aafe017
              
                Add Swift runtime library section
              
              
                kotlarmilos f4dca47
              
                Update projected methods to follow naming convention
              
              
                kotlarmilos 1605d31
              
                Remove SwiftStruct and SwiftEnumType attributes
              
              
                kotlarmilos c8110ee
              
                Update docs/README.md
              
              
                kotlarmilos b8841fd
              
                Update docs/README.md
              
              
                kotlarmilos 39eb1bd
              
                Update documentation to reflect changes in #2517
              
              
                kotlarmilos d81ec5f
              
                Fix formatting
              
              
                kotlarmilos File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -1,3 +1,142 @@ | ||
| # Documentation | ||
| # .NET Swift interop tooling documentation | ||
|  | ||
| This document outlines the functional design of the tooling and projections between Swift and .NET. | ||
| This document provides a detailed overview of the .NET Swift interop tooling, focusing on the projections between Swift and .NET, and the functional design of the tooling. The projection tooling is intended for use with C# and any other .NET language is beyond its scope. | ||
|  | ||
| ## Usage | ||
|  | ||
| The tooling consumes Swift interface files to generate C# bindings. Currently, the tool processes a Swift ABI file, which is generated from a `.swiftinterface` file by the Swift compiler. This ABI file contains a json representation of the abstract syntax tree of the `.swiftinterface` file. The `.swiftinterface` and `.abi.json` files are generated by executing the `swiftc` command with the `-emit-module-interface` option. In upcoming improvements, the ABI aggregator will transition to directly parsing the `.swiftinterface` file and, eventually, a dynamic library to facilitate type-strong parsing. | ||
|  | ||
| ``` | ||
| Description: | ||
| Swift bindings generator. | ||
|  | ||
| Usage: | ||
| SwiftBindings [options] | ||
|  | ||
| Options: | ||
| -a, --swiftabi <swiftabi> (REQUIRED) Path to the Swift ABI file. | ||
| -o, --output <output> (REQUIRED) Output directory for generated bindings. | ||
| -v, --verbose <verbose> Prints information about work in process. | ||
| -h, --help Display a help message. | ||
| --version Show version information | ||
| -?, -h, --help Show help and usage information | ||
| ``` | ||
|  | ||
| It is possible to specify multiple Swift ABI files for processing. If a unsupported type is encountered, the tooling will ignore it and generate C# source code for known syntax. | ||
|  | ||
| ## Projections | ||
|  | ||
| This section outlines the mappings between Swift and .NET types, and describes how the tool generates C# bindings for a Swift library. For types with similar semantics across Swift and .NET, direct interop is possible and bindings are generated. For types without direct projection, additional Swift wrappers are required and it is the user's responsibility to generate these wrappers. At this stage, the tool is designed to avoid generating any Swift code if possible to avoid complexity of maintaining different Swift compiler and SDK versions. The tool should only generate bindings for Swift types that are part of the stable ABI and don't evolve. | ||
|  | ||
| This section will be expanded as more support is introduced. | ||
|  | ||
| ### Primitive types | ||
|  | ||
| The table below lists the Swift types and their corresponding C# types. | ||
|  | ||
| | Swift Type | C# Type | | ||
| | ------------------------------- | -------- | | ||
| | `Swift.Int64` | `long` | | ||
| | `Swift.UInt64` | `ulong` | | ||
| | `Swift.Int32` | `int` | | ||
| | `Swift.UInt32` | `uint` | | ||
| | `Swift.Int16` | `short` | | ||
| | `Swift.UInt16` | `ushort` | | ||
| | `Swift.Int8` | `sbyte` | | ||
| | `Swift.UInt8` | `byte` | | ||
| | `Swift.UnsafeRawPointer` | `void*` | | ||
| | `Swift.UnsafeMutableRawPointer` | `void*` | | ||
| | `Int` | `nint` | | ||
| | `UInt` | `nuint` | | ||
| | `Bool` | `bool` | | ||
| | `Float` | `float` | | ||
| | `Double` | `double` | | ||
|  | ||
|  | ||
| All C# types mentioned are blittable except for `bool`. To facilitate `P/Invoke`, a lightweight wrapper is required to convert `bool` to `byte`. Swift primitive types are implemented as frozen structs that conform to Swift-specific lowering processes handled by the runtime. However, such mapping can fit within the underlying calling convention as these types are below the size limit for being passed by reference. | ||
|  | ||
| ### Static and P/Invoke functions | ||
|  | ||
| Each provided module is projected into a separate assembly. The assembly contains a namespace named `<ModuleName>Bindings` and includes a class named `<ModuleName>`. For each public function, a `P/Invoke` signature and a corresponding method are generated. Below is an example to illustrate this process. | ||
|  | ||
| Swift library example: | ||
| ```swift | ||
| public func sayHello() { | ||
| print("Hello world") | ||
| } | ||
| ``` | ||
|  | ||
| User's code in C#: | ||
| ```csharp | ||
| using System; | ||
| using HelloLibraryBindings; | ||
|  | ||
| namespace HelloWorld | ||
| { | ||
| public class Program | ||
| { | ||
| public static void Main(string[] args) | ||
| { | ||
| HelloLibrary.sayHello(); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|  | ||
| Generated bindings in C#: | ||
| ```csharp | ||
| using System; | ||
| using System.Runtime.InteropServices; | ||
| namespace HelloLibraryBindings | ||
| { | ||
| public class HelloLibrary | ||
| { | ||
| [DllImport("libHelloLibrary.dylib", EntryPoint = "$s12HelloLibrary03sayA0yyF")] | ||
| internal static extern void PIfunc_sayHello(); | ||
| public static void sayHello() | ||
| { | ||
| PIfunc_sayHello(); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|  | ||
| In the example, the user's code references the `HelloLibraryBindings` namespace and invokes a static method that has the same name as the Swift function. When the Swift function returns a type, the C# wrapper method also returns type, with additional processing if required. | ||
|  | ||
| ## Functional outline | ||
|  | ||
| The tooling consists of the following components: | ||
| - **SwiftBindings**: Command-line interface that orchestrates the tooling workflow. | ||
| - **SwiftReflector**: A library provides support for public ABI aggregation. It contains implementation of module declarations and the type system. | ||
| - **SwiftRuntimeLibrary**: Library that provides runtime marshaling support and projections of common Swift types. | ||
| - **SyntaxDynamo**: Library that provides an API for generating C# source code. | ||
|  | ||
| The general workflow for generating C# bindings from Swift code is as follows: | ||
| 1. Consume the Swift ABI file (`.abi.json`) and aggregate the public ABI using `ISwiftParser`, which generates a `ModuleDeclaration`. | ||
| 2. Generate C# source code based on the `ModuleDeclaration`. | ||
|  | ||
| ### Public ABI aggregation | ||
|  | ||
| The aggregation of the public ABI is managed through the `ISwiftParser` interface. This interface defines the layout for concrete implementations that are responsible for parsing and aggregating API information. There are two implementations: Swift ABI parser and Swift interface parser. The Swift ABI parser aggregates API information based on an ABI json file and doesn't contain metadata information from types. The Swift interface parser is designed to handle `.swiftinterface` file, which contains more information. The `.swiftinterface` file doesn't contain managled names and the parser consumes the dynamic library (`.dylib`) alongside to generate the `ModuleDeclaration`. | ||
|  | ||
| `ISwiftParser` interface: | ||
| ```csharp | ||
| using System; | ||
| using SwiftReflector.SwiftXmlReflection; | ||
|  | ||
| namespace SwiftReflector.Parser | ||
| { | ||
| public interface ISwiftParser | ||
| { | ||
| public ModuleDeclaration GetModuleDeclaration(string filePath, ErrorHandling errors); | ||
| } | ||
| } | ||
| ``` | ||
|  | ||
| ### Module declaration | ||
|  | ||
| The `ModuleDeclaration` serves as a integration point for public ABI aggregation and code generation phases. It contains ABI information for a module, including classes, structs, enums, protocols, functions, properties, extensions, and operators. | ||
|  | ||
| ### Code generation | ||
|  | ||
| Code generation involves a set compilers that convert `ModuleDeclaration` into C# source code. The `BindingsCompiler` and other specific compilers (i.e. `FunctionCompiler`) facilitating the generation of public-facing APIs using `SyntaxDynamo` library. | ||
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.