[][src]Crate safer_ffi

safer-ffi-banner

CI guide docs-rs crates-io repository

What is safer_ffi?

safer_ffi is a framework that helps you write foreign function interfaces (FFI) without polluting your Rust code with unsafe { ... } code blocks while making functions far easier to read and maintain.

📚 Read The User Guide 📚

Prerequisites

Minimum Supported Rust Version: 1.43.0

Quickstart

Cargo.toml

Edit your Cargo.toml like so:

[package]
name = "crate_name"
version = "0.1.0"
edition = "2018"

[lib]
crate-type = ["staticlib"]

[dependencies]
safer-ffi = { version = "*", features = ["proc_macros"] }

[features]
c-headers = ["safer-ffi/headers"]

src/lib.rs

This example is not tested
use ::safer_ffi::prelude::*;

/// A `struct` usable from both Rust and C
#[derive_ReprC]
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub
struct Point {
    x: f64,
    y: f64,
}

/* Export a Rust function to the C world. */
/// Returns the middle point of `[a, b]`.
#[ffi_export]
fn mid_point (
    a: &Point,
    b: &Point,
) -> Point
{
    Point {
        x: (a.x + b.x) / 2.,
        y: (a.y + b.y) / 2.,
    }
}

/// Pretty-prints a point using Rust's formatting logic.
#[ffi_export]
fn print_point (point: &Point)
{
    println!("{:?}", point);
}

/// The following test function is necessary for the header generation.
#[::safer_ffi::cfg_headers]
#[test]
fn generate_headers () -> ::std::io::Result<()>
{
    ::safer_ffi::headers::builder()
        .to_file("rust_points.h")?
        .generate()
}

Compilation & header generation

# Compile the C library (in `target/{debug,release}/libcrate_name.ext`)
cargo build # --release

# Generate the C header
cargo test --features c-headers -- generate_headers
Generated C header
/*! \file */
/*******************************************
 *                                         *
 *  File auto-generated by `::safer_ffi`.  *
 *                                         *
 *  Do not manually edit this file.        *
 *                                         *
 *******************************************/

#ifndef __RUST_CRATE_NAME__
#define __RUST_CRATE_NAME__

#ifdef __cplusplus
extern "C" {
#endif

/** \brief
 *  A `struct` usable from both Rust and C
 */
typedef struct {

    double x;

    double y;

} Point_t;

/** \brief
 *  Returns the middle point of `[a, b]`.
 */
Point_t mid_point (
    Point_t const * a,
    Point_t const * b);

/** \brief
 *  Pretty-prints a point using Rust's formatting logic.
 */
void print_point (
    Point_t const * point);


#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* __RUST_CRATE_NAME__ */

Testing it

main.c

#include <stdlib.h>

#include "rust_points.h"

int main (int argc, char const * const argv[])
{
    Point_t a = { .x = 84, .y = 45 };
    Point_t b = { .x = 0, .y = 39 };
    Point_t m = mid_point(&a, &b);
    print_point(&m);
    return EXIT_SUCCESS;
}

Compilation command

cc main.c -o main -L target/debug -l crate_name -l pthread -l dl

# Now feel free to run the compiled binary
./main

which outputs:

Point { x: 42.0, y: 42.0 }

🚀🚀

Re-exports

pub use tuple::*;

Modules

boxedfeature="alloc"

#[repr(C)] Boxed types.

char_p

char *-compatible strings (slim pointers), for easier use from within C. They thus do not support inner nulls, nor string appending.

closure

Closures with a #[repr(C)] layout (inlined vtable), up to 9 function arguments.

headersfeature="headers"

C headers generation.

layout

Trait abstractions describing the semantics of "being #[repr(C)]"

prelude
ptr

Wrappers around NonNull to better express the semantics of such pointer.

slice

Logic common to all fat pointers.

string

Rust string types with a defined #[repr(C)] layout, albeit not char * compatible (fat pointers).

tuple

Tuple types with a guaranteed #[repr(C)] layout.

vecfeature="alloc"

Macros

CType

Safely implement CType for a #[repr(C)] struct when all its fields are CType.

NULL
ReprC

Safely implement ReprC for a #[repr(C)] struct when all its fields are ReprC.

cfeature="proc_macros"

Creates a compile-time checked char_p::Ref<'static> out of a string literal.

c_vec

Structs

Stringfeature="alloc"

Same as String, but with guaranteed #[repr(C)] layout

Vecfeature="alloc"

Same as Vec<T>, but with guaranteed #[repr(C)] layout

Attribute Macros

cfg_headers
derive_ReprCfeature="proc_macros"

Safely implement ReprC for a #[repr(C)] struct when all its fields are ReprC.

ffi_export

Export a function to be callable by C.