cbindgen

repository·main·Indexed 25 days ago

https://github.com/mozilla/cbindgen

A tool for automatically generating C and C++ headers for Rust libraries that expose a public C API. It ensures generated headers reflect Rust's type layout and ABI guarantees. cbindgen can be used as a standalone CLI, integrated into a build.rs script as a Rust library, or configured via a cbindgen.toml file. It supports generating headers for C, C++, and Cython, and provides features for Swift binding generation and custom inline annotations to override global settings.

Tokens
8.8K
Snippets
20
Records
76
Agent score
84%

What's inside cbindgen

  1. Generate Swift Bindings

    main
    To generate idiomatic Swift names for imported functions (using NS_SWIFT_NAME or CF_SWIFT_NAME patterns), enable the swift_name_macro option in your cbindgen.toml. cbindgen will attempt to guess the appropriate method signature based on the function name and types.
  2. Use cbindgen as a library

    main
    Instead of using the standalone CLI, you can use cbindgen as a Rust library, typically within a build.rs script. This is useful for ensuring headers are regenerated automatically during the build process.
  3. Configure cbindgen via cbindgen.toml

    main
    Most cbindgen configuration is managed through a cbindgen.toml file. You can start with an empty file and add options as needed. Many options are specific to either C or C++ (e.g., features that leverage the C++ type system or generate helper methods).
  4. Use cbindgen as a standalone CLI

    main

    To generate headers from a Rust crate using the CLI, you need a cbindgen.toml configuration file and a Rust crate with a public C API.

    Run the following command to generate a C++ header:

    cbindgen --config cbindgen.toml --crate my_rust_library --output my_header.h

    To generate other languages, use the --lang flag:

    • For C: --lang c
    • For Cython: --lang cython
  5. Install cbindgen via cargo

    main

    To install the cbindgen standalone program, use the following command. The --force flag ensures that an existing installation is updated to the latest version.

    cargo install --force cbindgen
  6. Use cbindgen in a build.rs script

    main

    To integrate header generation directly into your Cargo build process, use the cbindgen library within your build.rs file.

    First, add cbindgen to your Cargo.toml under [build-dependencies]:

    [build-dependencies]
    cbindgen = "0.24.0"

    Then, implement the generation logic in build.rs using the Builder API:

    extern crate cbindgen;
    
    use std::env;
    
    fn main() {
        let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    
        cbindgen::Builder::new()
          .with_crate(crate_dir)
          .generate()
          .expect("Unable to generate bindings")
          .write_to_file("bindings.h");
    }
  7. Expose a public C API in Rust

    main

    To ensure cbindgen detects your items, you must use specific Rust attributes. cbindgen searches for:

    • Functions: #[no_mangle] pub extern fn
    • Globals: #[no_mangle] pub static
    • Constants: pub const

    Important Limitations:

    • cbindgen does not understand Rust's module system or namespacing. If two types have the same name in different modules, behavior is unspecified.
    • To ensure a type has a guaranteed layout in the generated header, use #[repr(...)] attributes (e.g., #[repr(C)], #[repr(u8)], or #[repr(transparent)]).
    • cbindgen cannot support anonymous tuples (A, B, ...) or wide pointers like &dyn Trait or &[T]. Use tuple structs and decompose slices into pointer/length pairs instead.
  8. Generate C/C++ headers using the CLI

    main

    To use cbindgen as a standalone program, you need a cbindgen.toml configuration file (which can be empty) and a Rust crate with a public C API.

    By default, cbindgen produces C++ headers. To produce C headers, use the --lang c flag.

  9. Use inline annotations to override global settings

    main

    You can override global cbindgen.toml settings by adding doc comments starting with cbindgen: to your Rust types. Annotations can be a bool, a string (no quotes), or a list of strings. If only the name is provided, =true is assumed.

    Warning: The annotation parser is naive and does not support escaping. Do not use =, ,, [ or ] within your annotation strings.

    /// cbindgen:field-names=[x, y]
    /// cbindgen:derive-eq
    #[repr(C)]
    pub struct Point(pub f32, pub f32);
  10. Configure includes and system headers

    main

    Control which headers are included in the generated file, including system headers (with angle brackets) and local headers (with quotes).

    # A list of sys headers to #include (with angle brackets)
    sys_includes = ["stdio", "string"]
    
    # A list of headers to #include (with quotes)
    includes = ["my_great_lib.h"]
    
    # Whether to suppress cbindgen's default C/C++ standard imports
    # (e.g., <stdint.h>, <stdarg.h> for C)
    no_includes = false
    
    # A block of text to add verbatim after the includes block
    after_includes = "#define VERSION 1"