prebindgen
A Rust utility crate for separating common FFI interface implementation and language-specific binding generation into different crates.
Problem
In Rust, #[no_mangle] extern "C"
functions must be defined in a cdylib
/staticlib
crate. Re-exporting them from a simple lib
crate doesn't work. The issue 2771 mentioning this problem is still open.
So when creating Rust libraries that need to expose FFI interfaces to multiple languages, you face a dilemma:
- Generate all bindings from the same crate (tight coupling)
- Manually duplicate FFI functions in each language-specific crate (code duplication)
Solution
prebindgen
solves this by generating #[no_mangle] extern "C"
source code from a common Rust library crate. Language-specific binding crates can then include this generated code and pass it to their respective binding generators (cbindgen, csbindgen, etc.).
How to Use
1. In the Common FFI Library Crate
Add dependencies to Cargo.toml
:
[]
= "0.1"
[]
= "0.1"
Mark structures and functions that are part of the FFI interface with the prebindgen
macro:
use ;
// Declare a public constant with the path to prebindgen data
pub const PREBINDGEN_OUT_DIR: &str = prebindgen_out_dir!;
Call init_prebindgen_out_dir()
in the crate's build.rs
:
// build.rs
2. In Language-Specific FFI Binding Crates
Add dependencies to Cargo.toml
:
[]
= { = "../my_common_ffi" }
[]
= { = "../my_common_ffi" }
= "0.1"
= "0.29" # for C bindings
Generate bindings in build.rs
:
Include the generated FFI code:
// In your lib.rs
include!;
Examples
See the examples directory for complete working examples:
- example-ffi: Common FFI library demonstrating prebindgen usage
- example-cbindgen: Language-specific binding using cbindgen for C headers
Documentation
- API Reference: See the docs.rs documentation for complete API details