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. // SAFETY: There is no other global function of this name.
  6. #[unsafe(no_mangle)]
  7. pub extern "C" fn analyze_numbers(x: c_int, y: c_int) {
  8.     if x < y {
  9.         println!("x ({x}) is smallest!");
  10.     } else {
  11.         println!("y ({y}) is probably larger than x ({x})");
  12.     }
  13. }

interoperability/rust/libanalyze/analyze.h

  1. #ifndef ANALYSE_H
  2. #define ANALYSE_H
  3. void analyze_numbers(int x, int y);
  4. #endif

interoperability/rust/libanalyze/Android.bp

  1. rust_ffi {
  2. name: "libanalyze_ffi",
  3. crate_name: "analyze_ffi",
  4. srcs: ["analyze.rs"],
  5. include_dirs: ["."],
  6. }

We can now call this from a C binary:

interoperability/rust/analyze/main.c

  1. #include "analyze.h"
  2. int main() {
  3. analyze_numbers(10, 20);
  4. analyze_numbers(123, 123);
  5. return 0;
  6. }

interoperability/rust/analyze/Android.bp

  1. cc_binary {
  2. name: "analyze_numbers",
  3. srcs: ["main.c"],
  4. static_libs: ["libanalyze_ffi"],
  5. }

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

  1. m analyze_numbers
  2. adb push "$ANDROID_PRODUCT_OUT/system/bin/analyze_numbers" /data/local/tmp
  3. adb shell /data/local/tmp/analyze_numbers

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