You’re reading a draft of the Ferrocene Language Specification. Some parts of this document might be missing, incomplete or incorrect. Our aim is to have the specification ready by the end of 2022.

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


AbiSpecification ::=
    extern AbiKind?

AbiKind ::=
  | 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 "Rust" - The default ABI of a Rust program, referred to as Rust ABI.

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

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

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

Implementation Permissions

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

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

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

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

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

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

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

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


extern "C"

21.2. External Blocks


ExternalBlock ::=
    unsafe? extern AbiSpecification? {

ExternItem ::=
    OuterAttributeOrDoc* (ExternalItemWithVisibility | TerminatedMacroInvocation)

ExternalItemWithVisibility ::=
    VisibilityModifier? (
      | 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 unsafe keyword of an external block is rejected, but may still be consumed by macros.


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 External functions and external statics inherit the ABI of their enclosing external block.

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

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

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

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 shall be referenced from an unsafe context.

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

Dynamic Semantics

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