Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
S

safer_ffi

> 编程语言
Open source

Write safer FFI code in Rust without polluting it with unsafe code

1.1K stars0 likes1 views
WebsiteGitHub

About

Write safer FFI code in Rust without polluting it with unsafe code

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.66.1

Quickstart

Click to hide

Small self-contained demo

You may try working with the examples/point example embedded in the repo:

bash
git clone https://github.com/getditto/safer_ffi && cd safer_ffi
(cd examples/point && make)

Otherwise, to start using ::safer_ffi, follow the following steps:

Crate layout

Step 1: Cargo.toml

Edit your Cargo.toml like so:

…
  • Where "x.y.z" ought to be replaced by the last released version, which you can find by running cargo search safer-ffi.

  • See the dedicated chapter on Cargo.toml for more info.

Step 2: src/lib.rs

Then, to export a Rust function to FFI, add the #[derive_ReprC] and #[ffi_export] attributes like so:

…
  • See the dedicated chapter on src/lib.rs for more info.

Step 3: src/bin/generate-headers.rs

rust
fn main() -> ::std::io::Result {
    ::crate_name::generate_headers()
}

Compilation & header generation

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

# Generate the C header
cargo run --features headers --bin generate-headers
  • See the dedicated chapter on header generation for more info.

Generated C header (rust_points.h)

…

Testing it from C

Here is a basic example to showcase FFI calling into our exported Rust functions:

main.c

c
#include 

#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

bash
cc -o main{,.c} -L target/debug -l crate_name -l{pthread,dl,m}

# Now feel free to run the compiled binary
./main
  • Note regarding the extra -l… flags.

    Those vary based on the version of the Rust standard library being used, and the system being used to compile it. In order to reliably know which ones to use, rustc itself ought to be queried for it.

    Simple command:

    bash
    rustc --crate-type=staticlib --print=native-static-libs -&1 | sed -nE 's/^note: native-static-libs: (.*)/\1/p'

    Ideally, you would not query for this information in a vacuum (e.g., /dev/null file being used as input Rust code just above), and rather, would apply it for your actual code being compiled:

    bash
    cargo rustc -q -- --print=native-static-libs \
        2>&1 | sed -nE 's/^note: native-static-libs: (.*)/\1/p'

    And if you really wanted to polish things further, you could use the JSON-formatted compiler output (this, for instance, avoids having to redirect stderr). But then you'd have to use a JSON parser, such as jq:

    bash
    RUST_STDLIB_DEPS=$(set -eo pipefail && \
        cargo rustc \
            --message-format=json \
            -- --print=native-static-libs \
        | jq -r '
            select (.reason == "compiler-message")
            | .message.message
        ' | sed -nE 's/^native-static-libs: (.*)/\1/p' \
    )

    and then use:

    bash
    cc -o main{,.c} -L target/debug -l crate_name ${RUST_STDLIB_DEPS}

which does output:

Point { x: 42.0, y: 42.0 }

Development

Click to see

To test the code with a certain amount of FFI integration baked into the tests (since safer-ffi, alone, only exports APIs to the FFI, so doesn't come with FFI callsites on its own), the ffi_tests/ project directory is used to test against C, C#, and Lua callsites.

You can run these tests directly by doing:

bash
make -C ffi_tests

or by adding --features ffi-tests to the cargo test command.

Formatting

Code is formatted using the "{MSRV}-nightly toolchain". That is, formatting uses some unstable features of rustfmt, so we use a Versioned Nightly™ approach. For the sake of version consistency, we stick to that of our MSRV.

But since it needs to be a genuine nightly toolchain, we are forced to pick an actual nightly toolchain, only one whose date matches the birth of the corresponding MSRV-stable toolchain.

  • See ./scripts/formatting/rust-toolchain.toml.
  • See also, w.r.t. versions and dates:

To format the code, you have three options:

  • ./scripts/format.sh

  • cargo fmt-nightly (which is defined as an alias of the previous bullet)

  • cargo fmt but only after having run ./scripts/formatting/setup_cargo_fmt_override.sh at least once.

    This does mutate a bit your rustup setup, but in an unobservable way (but for allowing the matching stable toolchain to use unstable features when running cargo fmt, the very point of this maneuver).

    This is probably the preferred approach for those with IDEs or whatnot which automagically runs cargo fmt/rustfmt on save.

Dependencies

  • Lua dependencies

    For running the C# FFI integration tests please install dotnet (v8.0) dependency:

    See for guidance about this.

  • Lua dependencies

    For running Lua FFI integration tests please install luajit dependency:

    MacOS:

    bash
    brew install luajit

    Ubuntu/Debian:

    bash
    sudo apt-get install -y luajit

Various integration test suites

safer-ffi includes three different tests suites that can be run.

bash
# In the project root:
cargo test

# FFI tests

make -C ffi_tests

# JavaScript tests

make -C js_tests

# Running the JS tests also gives you instructions for running browser tests.
# Run this command in the `js_tests` directory, open a browser and navigate to
# http://localhost:13337/
wasm-pack build --target web && python3 -m http.server 13337

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Rust

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言