#[ffi_export]

This is a very simple attribute: simply slap it on an "item" that you wish to export to the FFI world (C), and voilà!

The only currently supported such "item"s are function definitions: const and statics are not supported yet. This ought to be fixed soon.

use ::safer_ffi::prelude::*;

#[ffi_export]
fn adder (x: i32, y: i32) -> i32
{
    x.wrapping_add(y)
}

Requirements

  • all the types used in the function signature need to be ReprC

    This is the core property that ensures both the safety of exporting such functions to the FFI (contrary to the rather poor improper_ctypes lint and its false positives) and the associated C-header-generating logic.

  • The only allowed generic parameters of the function are lifetime parameters.

    • That is, the following function definition is valid:

      use ::safer_ffi::prelude::*;
      
      #[ffi_export]
      fn max<'xs> (xs: c_slice::Ref<'xs, i32>)
        -> Option<&'xs i32>
      {
          xs  .as_slice()  // : &'xs [i32]
              .iter()
              .max()
      }
      
    • But the following one is not:

      use ::safer_ffi::prelude::*;
      
      #[derive_ReprC]
      #[repr(C)]
      #[derive(Default)]
      pub
      struct Point<Coordinate> {
          x: Coordinate,
          y: Coordinate,
      }
      
      #[ffi_export] // Error, generic _type_ parameter
      fn origin<Coordinate> ()
        -> Point<Coordinate>
      where
          Coordinate : Default,
      {
          Point::default()
      }