Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Взаимодействие с Java

Java может загружать разделяемые объекты через Java Native Interface (JNI). Крейт jni позволяет создать совместимую библиотеку.

Сначала создадим функцию Rust для экспорта в Java:

interoperability/java/src/lib.rs:

#![allow(unused)]
fn main() {
// Copyright 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0

//! Демонстрация FFI Rust <-> Java.

use jni::JNIEnv;
use jni::objects::{JClass, JString};
use jni::sys::jstring;

/// Реализация метода HelloWorld::hello.
// SAFETY: Нет другой глобальной функции с таким именем.
#[unsafe(no_mangle)]
pub extern "system" fn Java_HelloWorld_hello(
    mut env: JNIEnv,
    _class: JClass,
    name: JString,
) -> jstring {
    let input: String = env.get_string(&name).unwrap().into();
    let greeting = format!("Hello, {input}!");
    let output = env.new_string(greeting).unwrap();
    output.into_raw()
}
}

interoperability/java/Android.bp:

rust_ffi_shared {
    name: "libhello_jni",
    crate_name: "hello_jni",
    srcs: ["src/lib.rs"],
    rustlibs: ["libjni"],
}

Затем вызываем эту функцию из Java:

interoperability/java/HelloWorld.java:

class HelloWorld {
    private static native String hello(String name);

    static {
        System.loadLibrary("hello_jni");
    }

    public static void main(String[] args) {
        String output = HelloWorld.hello("Алиса");
        System.out.println(output);
    }
}

interoperability/java/Android.bp:

java_binary {
    name: "helloworld_jni",
    srcs: ["HelloWorld.java"],
    main_class: "HelloWorld",
    jni_libs: ["libhello_jni"],
}

Наконец, можно собрать, синхронизировать и запустить бинарный файл:

m helloworld_jni
adb sync  # requires adb root && adb remount
adb shell /system/bin/helloworld_jni
  • Атрибут unsafe(no_mangle) указывает Rust выдать символ Java_HelloWorld_hello ровно так, как он записан. Это важно, чтобы Java узнала символ как метод hello класса HelloWorld.

    • По умолчанию Rust искажает (переименовывает) символы, чтобы бинарный файл мог слинковать две версии одного и того же крейта Rust.