The Bridge Module

With swift-bridge you use a "bridge module" in order to declare your FFI interface.


#![allow(unused)]
fn main() {
#[swift_bridge::bridge]
mod ffi {
    // Export Rust types and functions for Swift to use.
    extern "Rust" {
        type SomeRustType;
        fn some_type_method(&mut self) -> String;
    }

    // Import Swift types and functions for Swift to use.
    extern "Swift" {
        type SomeSwiftClass;

        #[swift_bridge(swift_name = "someClassMethod")]
        fn some_class_method(&self, arg: u8);
    }
}
}

Your bridge module can contain any number of extern "Rust" and extern "Swift" blocks, each declaring types and functions to expose to and import from Swift, respectively.

How it Works

After you declare your bridge module, you use two code generators at build time to make the FFI layer that you described work.

One code generator generates the Rust side of the FFI layer, and the other code generator produces the Swift side.

Rust code generation

The #[swift_bridge::bridge] procedural macro parses your bridge module at compile time and then generates the Rust side of your FFI layer.

Swift code generation

At build time you run swift-bridge-build (or swift-bridge-cli for non-Cargo based setups) on files that contain bridge modules in order to generate the Swift and C code necessary to make your bridge work.

Let's Begin

This section's sub chapters will go into detail about the different ways that you can use bridge modules to connect Rust and Swift.

In the meantime, here's a quick peak of a simple bridge module:


#![allow(unused)]
fn main() {
// We use the `swift_bridge::bridge` macro to declare a bridge module.
// Then at build time the `swift-bridge-build` crate is used to generate
// the corresponding Swift and C FFI glue code.
#[swift_bridge::bridge]
mod ffi {
    // Create "transparent" structs where both Rust and Swift can directly access the fields.
    struct AppConfig {
        file_manager: CustomFileManager,
    }

    // Transparent enums are also supported.
    enum UserLookup {
        ById(UserId),
        ByName(String),
    }

    // Export opaque Rust types, functions and methods for Swift to use.
    extern "Rust" {
        type RustApp;

        #[swift_bridge(init)]
        fn new(config: AppConfig) -> RustApp;
        
        fn get_user(&self, lookup: UserLookup) -> Option<&User>;
    }

    extern "Rust" {
        type User;
        type MessageBoard;

        #[swift_bridge(get(&nickname))]
        fn informal_name(self: &User) -> &str;
    }

    // Import opaque Swift classes and functions for Rust to use.
    extern "Swift" {
        type CustomFileManager;
        fn save_file(&self, name: &str, contents: &[u8]);
    }
}

struct User {
    nickname: String
}
}