Using Bindgen
The bindgen tool can auto-generate bindings from a C header file.
First create a small C library:
interoperability/bindgen/libbirthday.h:
1. typedef struct card {
2. const char* name;
3. int years;
4. } card;
6. void print_card(const card* card);
interoperability/bindgen/libbirthday.c:
1. #include <stdio.h>
2. #include "libbirthday.h"
4. void print_card(const card* card) {
5. printf("+--------------\n");
6. printf("| Happy Birthday %s!\n", card->name);
7. printf("| Congratulations with the %i years!\n", card->years);
8. printf("+--------------\n");
9. }
Add this to your Android.bp file:
interoperability/bindgen/Android.bp:
1. cc_library {
2. name: "libbirthday",
3. srcs: ["libbirthday.c"],
4. }
Create a wrapper header file for the library (not strictly needed in this example):
interoperability/bindgen/libbirthday_wrapper.h:
1. #include "libbirthday.h"
You can now auto-generate the bindings:
interoperability/bindgen/Android.bp:
1. rust_bindgen {
2. name: "libbirthday_bindgen",
3. crate_name: "birthday_bindgen",
4. wrapper_src: "libbirthday_wrapper.h",
5. source_stem: "bindings",
6. static_libs: ["libbirthday"],
7. }
Finally, we can use the bindings in our Rust program:
interoperability/bindgen/Android.bp:
1. rust_binary {
2. name: "print_birthday_card",
3. srcs: ["main.rs"],
4. rustlibs: ["libbirthday_bindgen"],
5. }
interoperability/bindgen/main.rs:
1. ```
//! Bindgen demo.
```
3. ```
use birthday_bindgen::{card, print_card};
```
5. ```
fn main() {
```
6. ```
let name = std::ffi::CString::new("Peter").unwrap();
```
7. ```
let card = card { name: name.as_ptr(), years: 42 };
```
8. ```
// SAFETY: The pointer we pass is valid because it came from a Rust
```
9. ```
// reference, and the `name` it contains refers to `name` above which also
```
10. ```
// remains valid. `print_card` doesn't store either pointer to use later
```
11. ```
// after it returns.
```
12. ```
unsafe {
```
13. ```
print_card(&card as *const card);
```
14. ```
}
```
15. ```
}
```
Build, push, and run the binary on your device:
1. m print_birthday_card
2. adb push "$ANDROID_PRODUCT_OUT/system/bin/print_birthday_card" /data/local/tmp
3. adb shell /data/local/tmp/print_birthday_card
Finally, we can run auto-generated tests to ensure the bindings work:
interoperability/bindgen/Android.bp:
1. rust_test {
2. name: "libbirthday_bindgen_test",
3. srcs: [":libbirthday_bindgen"],
4. crate_name: "libbirthday_bindgen_test",
5. test_suites: ["general-tests"],
6. auto_gen_config: true,
7. clippy_lints: "none", // Generated file, skip linting
8. lints: "none",
9. }
1. atest libbirthday_bindgen_test
