Types

Types that can be used in both forward interop (foreign calling Rust) and reverse interop (Rust calling foreign plugins).

Structs

Regular structs with fields. The #[ffi] attribute handles everything needed for the FFI boundary. Unless otherwise stated, every contained field has to be a supported #[ffi] type again.

#[ffi]
pub struct Vec3f32 {
    x: f32,
    y: f32,
    z: f32,
}

// Single-field tuple structs are supported too
#[ffi]
pub struct Tupled(u8);

Enums

C-style enums, enums with explicit discriminants, and enums with data payloads (tagged unions). At the moment, only enums with a single payload item per variant are supported. Unless otherwise stated, every contained variant payload has to be a supported #[ffi] type again.

#[ffi]
pub enum EnumDocumented {
    /// Variant A.
    A,
    /// Variant B.
    B,
}

#[ffi]
pub enum EnumPayload {
    A,
    B(Vec3f32),
    C(u32),
}

#[ffi]
pub enum EnumNegative {
    A = -1,
    B = 0,
    C = 1,
}

Opaque Types

Mark a struct #[ffi(opaque)] to hide its layout from foreign code entirely. The struct can only ever be passed by pointer.

#[ffi(opaque)]
pub struct SomeContext {
    some_field: u32,
}

Generic Types

Structs and enums can be generic over type parameters, lifetimes, and const generics. Each concrete monomorphisation you register becomes a distinct type in the generated bindings.

#[ffi]
pub struct Generic<'a, T: TypeInfo> {
    x: &'a T,
}

#[ffi]
pub struct FixedString<const N: usize> {
    data: [u8; N],
}

Fixed-Size Arrays

Fixed-size arrays are supported as struct fields.

#[ffi]
pub struct Array {
    data: [u8; 16],
}

Transparent & Packed

  • #[ffi(transparent)] makes a newtype wrapper transparent to the FFI boundary.
  • #[ffi(packed)] produces a tightly packed struct.
#[ffi(transparent)]
pub struct Transparent(Tupled);

#[ffi(packed)]
pub struct Packed1 {
    x: u8,
    y: u16,
}

Naming & Organisation

Renaming

Override the generated name with #[ffi(name = "...")].

#[ffi(name = "EnumRenamed")]
pub enum EnumRenamedXYZ { X }

#[ffi(name = "StructRenamed")]
pub struct StructRenamedXYZ { pub e: EnumRenamedXYZ }

Modules / Namespaces

Assign types to logical namespaces in the generated output.

#[ffi(module = "math")]
pub struct Vec { x: f64, y: f64 }

Constants

Export Rust const values.

#[ffi]
pub const U8: u8 = u8::MAX;

#[ffi]
pub const COMPUTED_I32: i32 = f(i32::MAX);

Skipping

Use #[ffi::skip] on fields or methods you want to exclude from bindings.

#[ffi]
pub struct Phantom<'a, T: 'static + TypeInfo> {
    pub x: u32,
    #[ffi::skip]
    pub p: PhantomData<&'a T>,
}