Javaとの相互運用性
Javaは Java Native Interface (JNI) を介して共有オブジェクトを読み込めます。 jni クレートを使うと、互換性のある ライブラリを作成できます。
まず、JavaにエクスポートするRust関数を作成します:
interoperability/java/src/lib.rs:
#![allow(unused)] fn main() { // 著作権 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 //! Rust <-> Java FFI demo. use jni::JNIEnv; use jni::objects::{JClass, JString}; use jni::sys::jstring; /// HelloWorld::hello method implementation. // SAFETY: There is no other global function of this name. #[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("Alice");
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がそのシンボルをHelloWorldクラスのhelloメソッドとして認識できるようにするために重要です。- デフォルトでは、Rustはシンボルをマングル(名前変更)するため、1つのバイナリに 同じRustクレートの2つのバージョンをリンクできます。