Using Bindgen

The bindgen tool can auto-generate bindings from a C header file.

Create a wrapper header file for the library (not strictly needed in this example):

interoperability/bindgen/libbirthday_wrapper.h:

#include "libbirthday.h"

interoperability/bindgen/Android.bp:

rust_bindgen { name: "libbirthday_bindgen", crate_name: "birthday_bindgen", wrapper_src: "libbirthday_wrapper.h", source_stem: "bindings", static_libs: ["libbirthday"], }

Finally, we can use the bindings in our Rust program:

interoperability/bindgen/Android.bp:

rust_binary { name: "print_birthday_card", srcs: ["main.rs"], rustlibs: ["libbirthday_bindgen"], static_libs: ["libbirthday"], }

interoperability/bindgen/main.rs:

//! Bindgen demo. use birthday_bindgen::{card, print_card}; fn main() { let name = std::ffi::CString::new("Peter").unwrap(); let card = card { name: name.as_ptr(), years: 42 }; // SAFETY: The pointer we pass is valid because it came from a Rust // reference, and the `name` it contains refers to `name` above which also // remains valid. `print_card` doesn't store either pointer to use later // after it returns. unsafe { print_card(&card as *const card); } }

Speaker Notes

  • The Android build rules will automatically call bindgen for you behind the scenes.

  • Notice that the Rust code in main is still hard to write. It is good practice to encapsulate the output of bindgen in a Rust library which exposes a safe interface to caller.