Calling Rust

Exporting Rust functions and types to C is easy:

interoperability/rust/libanalyze/analyze.rs

  1. //! Rust FFI demo.
  2. #![deny(improper_ctypes_definitions)]
  3. use std::os::raw::c_int;
  4. /// Analyze the numbers.
  5. #[no_mangle]
  6. pub extern "C" fn analyze_numbers(x: c_int, y: c_int) {
  7. if x < y {
  8. println!("x ({x}) is smallest!");
  9. } else {
  10. println!("y ({y}) is probably larger than x ({x})");
  11. }
  12. }

interoperability/rust/libanalyze/analyze.h

#ifndef ANALYSE_H #define ANALYSE_H extern "C" { void analyze_numbers(int x, int y); } #endif

interoperability/rust/libanalyze/Android.bp

rust_ffi { name: "libanalyze_ffi", crate_name: "analyze_ffi", srcs: ["analyze.rs"], include_dirs: ["."], }

We can now call this from a C binary:

interoperability/rust/analyze/main.c

#include "analyze.h" int main() { analyze_numbers(10, 20); analyze_numbers(123, 123); return 0; }

interoperability/rust/analyze/Android.bp

cc_binary { name: "analyze_numbers", srcs: ["main.c"], static_libs: ["libanalyze_ffi"], }

Build, push, and run the binary on your device:

$ m analyze_numbers $ adb push $ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/tmp $ adb shell /data/local/tmp/analyze_numbers

#[no_mangle] disables Rust’s usual name mangling, so the exported symbol will just be the name of the function. You can also use #[export_name = "some_name"] to specify whatever name you want.