Quickstart
This walkthrough takes you from an empty directory to a generated C header in
about five minutes. It assumes you have already
installed cheadergen.
1. Create a tiny Rust library
cargo new --lib distance
cd distance
Edit Cargo.toml so the crate compiles as a C-compatible static library:
[package]
name = "distance"
version = "0.1.0"
edition = "2024"
[lib]
# 👇 Change the crate type from the default `rlib` to `staticlib`
crate-type = ["staticlib"]
Replace src/lib.rs:
#![allow(unused)]
fn main() {
#[repr(C)]
pub struct Point {
pub x: f64,
pub y: f64,
}
#[unsafe(no_mangle)]
pub extern "C" fn distance(a: Point, b: Point) -> f64 {
((a.x - b.x).powi(2) + (a.y - b.y).powi(2)).sqrt()
}
}
Why these annotations?
#[unsafe(no_mangle)]keeps the symbol name intact so a C linker can resolve it.extern "C"makes the function use the C calling convention so a C caller passes arguments and reads the return value the way Rust expects. Together they makedistancecallable from C. Without them,cheadergenhas no signal that you intend the function to be reachable from C and skips it.Same reasoning applies to
Point:#[repr(C)]guarantees that the struct’s layout matches a C struct. Without it,cheadergenwould refuse to emit a C definition for it.
2. Generate the header
cheadergen generate --output-dir include
You should see something like:
Generating headers for 1 crate(s) using toolchain `nightly-...`
Successfully loaded rustdoc JSON for `distance`: root module `distance`
`distance`: 1 function(s), 0 static(s), 0 constant(s)
Wrote target header: include/distance.h
3. Read the output
In include/distance.h you should see something along the lines of:
/* WARNING: this file was auto-generated by
* cheadergen from `distance`.
* Do not edit it manually. */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
double x;
double y;
} Point;
double distance(Point a, Point b);
That’s the whole loop. To understand how the generated C header is structured (and how to customise it), read Anatomy of a generated header.
Where to go next
- Customise emission via
cheadergen.toml. - Customise how Rust items are exposed to C via
#[cheadergen::config(...)]. Start from the annotations mental model. - Wire header generation into your build system with Integrate with Cargo.