prebindgen
A tool for separating the implementation of FFI interfaces from language-specific binding generation, allowing each to reside in different crates.
Problem
When creating Rust libraries that need to expose FFI interfaces to multiple languages, it may be preferable to create separate cdylib
or staticlib
crates for each language-specific binding. This allows you to tailor each crate to the requirements and quirks of its binding generator and to specifics of the destination language.
However, #[no_mangle] extern "C"
functions can only be defined in a cdylib
or staticlib
crate, and cannot be exported from a lib
crate. As a result, these functions must be duplicated in each language-specific binding crate. This duplication is inconvenient for large projects with many FFI functions and types.
Solution
prebindgen
solves this by generating #[no_mangle] extern "C"
Rust proxy source code from a common Rust library crate. Language-specific binding crates can then compile this generated code and pass it to their respective binding generators (such as cbindgen, csbindgen, etc.).
Usage
1. In the Common FFI Library Crate (e.g., example_ffi
)
Mark structures and functions that are part of the FFI interface with the prebindgen
macro:
// example-ffi/src/lib.rs
use ;
// Declare a public constant with the path to prebindgen data:
pub const PREBINDGEN_OUT_DIR: &str = prebindgen_out_dir!;
// Group structures and functions for selective handling
Call init_prebindgen_out_dir()
in the crate's build.rs
:
// example-ffi/build.rs
2. In Language-Specific FFI Binding Crate (named e.g. example-cbindgen
)
Add the common FFI library to build dependencies:
# example-cbindgen/Cargo.toml
[]
= { = "../example_ffi" }
= "0.2"
= "0.24"
// example-cbindgen/build.rs
use ;
use Itertools;
Include the generated Rust files in your project to build the static or dynamic library itself:
// lib.rs
include!;
Examples
See example projects on https://github.com/milyin/prebindgen/tree/main/examples
- example-ffi: Common FFI library demonstrating prebindgen usage
- example-cbindgen: Language-specific binding using cbindgen for C headers
Documentation
- prebindgen API Reference: docs.rs/prebindgen
- prebindgen-proc-macro API Reference: docs.rs/prebindgen-proc-macro