bindgen

repository·main·Indexed 26 days ago

https://github.com/rust-lang/rust-bindgen

A tool for automatically generating Rust FFI bindings from C and C++ header files. It parses headers to produce equivalent Rust structs, enums, and function declarations, enabling interoperability between Rust and native C libraries. Includes a CLI for configuring binding generation, support for custom derives and attributes, and allowlisting/blocklisting of items.

Tokens
15.7K
Snippets
38
Records
102
Agent score
90%

What's inside bindgen

  1. Introduction to rust-bindgen

    main
    rust-bindgen is a tool used to generate Rust FFI (Foreign Function Interface) bindings from C and C++ headers. It allows Rust code to interact with existing C/C++ libraries by automatically creating the necessary Rust declarations for types, functions, and constants.
  2. Overview of rust-bindgen

    main
    bindgen is a tool that automatically generates Rust FFI (Foreign Function Interface) bindings to C and some C++ libraries. It parses C header files and produces equivalent Rust structs, enums, and function declarations, allowing Rust code to call into C libraries safely and easily.
  3. Generate Rust FFI bindings from C and C++ headers

    main

    Use bindgen to automatically generate Rust Foreign Function Interface (FFI) bindings for C and C++ libraries. This allows you to call C/C++ functions and use their types directly within Rust code by translating header files into equivalent Rust structs and extern "C" blocks.

    /* Input: C header (cool.h) */
    typedef struct CoolStruct {
        int x;
        int y;
    } CoolStruct;
    
    void cool_function(int i, char c, CoolStruct* cs);
    /* Output: Generated Rust code */
    #[repr(C)]
    pub struct CoolStruct {
        pub x: ::std::os::raw::c_int,
        pub y: ::std::os::raw::c_int,
    }
    
    extern "C" {
        pub fn cool_function(i: ::std::os::raw::c_int,
                             c: ::std::os::raw::c_char,
                             cs: *mut CoolStruct);
    }
  4. Build Clang from source for bindgen

    main

    If your package manager does not provide Clang 9.0 or greater, you must build it from source. When building for bindgen, follow these requirements:

    1. Checkout and build clang.
    2. Checkout and build clang-tools-extra.

    Note: You do not need to checkout or build compiler-rt or libcxx.

  5. Treat a type as an opaque blob of bytes using C++ annotations

    main

    You can mark a type as opaque directly in your C++ source code using a special comment annotation. This is useful for providing hints to bindgen without changing the CLI command or the Rust builder logic.

    /// <div rustbindgen opaque></div>
    class Foo {
        // ...
    };
  6. Configure Rust target version for union support

    main

    To use Rust's native union builtin, you must target Rust version 1.19 or higher (including nightly). By default, bindgen targets the latest stable Rust. You can specify a target using the --rust-target CLI flag or the bindgen::Builder::rust_target() method.

    Note: The --unstable-rust option is deprecated; use --rust-target nightly instead.

  7. Use allowlisting to limit generated bindings

    main
    By default, bindgen generates bindings for everything in the provided header files. To reduce noise or avoid unsupported C++ features, you can use allowlisting. When allowlisting rules are specified, bindgen only generates bindings for types, functions, and global variables that match the rules, or are transitively used by a definition that matches them.
  8. Replace a C++ type with another type using the `replaces` annotation

    main

    Use the replaces annotation within a comment block in your C or C++ header to substitute a complex type with a simpler one. This is useful when a structure is too complex for bindgen to parse correctly (e.g., due to custom destructors preventing automatic trait derivation).

    When you use replaces="TypeName", bindgen will generate bindings for TypeName using the definition provided by the annotated type instead.

    /**
     * <div rustbindgen replaces="nsTArray"></div>
     */
    template<typename T>
    class nsTArray_Simple {
      T* mBuffer;
    public:
      ~nsTArray_Simple() {};
    };
  9. Annotate types with `#[must_use]` using C annotations

    main

    You can trigger the #[must_use] attribute for a specific type directly in your C source code by using a special rustbindgen comment block within the Doxygen-style comment of the type definition. Use the mustusetype tag inside a div.

    /** <div rustbindgen mustusetype></div> */
    struct ErrorType {
        // ...
    };
  10. Handle bindgen generated padding fields

    main

    bindgen may generate padding fields named __bindgen_padding_N depending on the architecture and toolchain. To avoid manual initialization errors (as these fields may vary across architectures), use the Default trait.

    Option 1: Enable automatic derivation Enable the derive_default method when constructing your bindgen::Builder.

    Option 2: Manual implementation Implement Default for the struct manually using std::mem::zeroed():

    impl Default for SRC_DATA {
        fn default() -> Self {
            unsafe { std::mem::zeroed() }
        }
    }

    Then, initialize your struct using the struct update syntax to automatically handle padding:

    SRC_DATA {
        field_a: "foo",
        field_b: "bar",
        ..Default::default()
    }
    // Example of using struct update syntax with Default to handle padding
    SRC_DATA {
        field_a: "foo",
        field_b: "bar",
        ..Default::default()
    }