21. FFI

Legality Rules

21:1 Foreign Function Interface or FFI employs ABI, attributes, external blocks, external functions, linkage, and type layout to interface a Rust program with foreign code.

21:2 The following attributes affect FFI:

21.1. ABI

Syntax

AbiSpecification ::=
    extern AbiKind?

AbiKind ::=
    RawStringLiteral
  | StringLiteral

Legality Rules

21.1:1 Application Binary Interface or ABI is a set of conventions that dictate how data and computation cross language boundaries.

21.1:2 The ABI kind indicates the ABI of a construct.

21.1:3 The following ABIs are supported:

  • 21.1:4 extern "C" - The default ABI of C code, referred to as extern C ABI.

  • 21.1:5 extern "C-unwind" - The same as extern "C" with the addition that unwinding across FFI is permitted.

  • 21.1:6 extern "Rust" - The default ABI of a Rust program, referred to as Rust ABI.

  • 21.1:7 extern "system" - The operating system-dependent ABI, referred to as external system ABI.

21.1:8 A function without an explicit ABI has implicit Rust ABI, unless it appears within an external block.

21.1:9 A function with an ABI but without a specified ABI kind has implicit extern C ABI.

Implementation Permissions

21.1:10 A tool is allowed to specify additional ABIs. These ABIs may include, but may not be limited to, the following:

  • 21.1:11 extern "aapcs" - The ARM ABI.

  • 21.1:12 extern "cdecl" - The x86_32 ABI of C code.

  • 21.1:13 extern "fastcall" - The fastcall ABI that corresponds to MSVC’s __fastcall and GCC and clang’s __attribute__((fastcall)).

  • 21.1:14 extern "stdcall" - The x86_32 ABI of the Win32 API.

  • 21.1:15 extern "sysv64" - The x86_64 non-Windows ABI of C code.

  • 21.1:16 extern "vectorcall" - The vectorcall ABI that corresponds to MSVC’s __vectorcall and clang’s __attribute__((vectorcall)).

  • 21.1:17 extern "win64" - The x86_64 Windows ABI of C code.

Undefined Behavior

21.1:18 It is undefined behavior when a foreign exception crosses a foreign function interface boundary with an ABI other than extern "C-unwind".

Examples

extern
extern "C"

21.2. External Blocks

Syntax

ExternalBlock ::=
    unsafe? extern AbiKind? {
      InnerAttributeOrDoc*
      ExternItem*
    }

ExternItem ::=
    OuterAttributeOrDoc* (ExternalItemWithVisibility | TerminatedMacroInvocation)

ExternalItemWithVisibility ::=
    VisibilityModifier? (
        FunctionDeclaration
      | StaticDeclaration
    )

Legality Rules

21.2:1 An external block is a construct that provides the declarations of foreign functions as unchecked imports.

21.2:2 The ABI of a extern block is determined as follows:

21.2:5 The unsafe keyword of an external block is rejected, but may still be consumed by macros.

Examples

extern "C" {
    static MAX_LENGTH: size_t;

    fn compress
        (input: *const u8,
         input_length: size_t,
         compressed: *mut u8,
         compressed_length: *mut size_t) -> c_int;
    fn log(msg: *const c_char, ...);
}

21.3. External Functions

Legality Rules

21.3:1 An external function is an unchecked import of a foreign function.

21.3:2 An external function shall be invoked from an unsafe context.

21.3:3 An external function shall not specify a FunctionQualifierList.

21.3:4 An external function inherits the ABI of its enclosing external block.

21.3:5 An external function shall not specify a GenericParameterList containing constant parameters or type parameters.

21.3:6 An external function shall not specify a FunctionBody.

21.3:7 An external function shall not specify patterns other than identifier patterns and underscore patterns.

21.3:8 Only the last parameter FunctionParameter of an external function may specify a FunctionParameterVariadicPart.

21.4. External Statics

Legality Rules

21.4:1 An external static is an import of a foreign variable.

21.4:2 An external static inherits the ABI of its enclosing external block.

21.4:3 An external static shall be referenced from an unsafe context.

21.4:4 An external static shall not specify a static initializer.

Dynamic Semantics

21.4:5 An immutable external static shall be initialized before Rust code is executed.