#![allow(non_snake_case, non_camel_case_types, dead_code)] use jnim::{JInt, JVm, JVoid}; mod hello { use std::ops::Deref; use jnim::{CachedID, JClassID, JEnv, JInt, JNameMaker, JObject, JPlainMarker, JVm}; struct Hello { __supper: JObject, __myinterface: MyInterfaceObject, } impl Deref for Hello { type Target = JObject; fn deref(&self) -> &Self::Target { &self.__supper } } impl AsRef for Hello { fn as_ref(&self) -> &JObject { &self.__supper } } impl JNameMaker for Hello { const JAVA_PATH: &'static [u8] = b"Hello\0"; } impl JPlainMarker for Hello { fn class(env: Option<&JEnv>) -> Option { static CACHE: CachedID = CachedID::new(); CACHE.get(|| JEnv::env(env)?.find_class(Self::JAVA_PATH)) } } impl Hello { fn play(&self, env: &JEnv) -> Option<()> { static CACHE: CachedID = CachedID::new(); CACHE .get(|| Self::class(Some(env))?.method(env, b"play\0", b"()V\0"))? .call(env, self.as_ref(), ()) } } impl MyInterface for Hello {} impl AsRef for Hello { fn as_ref(&self) -> &MyInterfaceObject { &self.__myinterface } } trait MyInterface: AsRef { fn MyInterface_class(env: Option<&JEnv>) -> Option { const MY_INTERFACE_NAME: &'static [u8] = b"MyInterface\0"; static CACHE: CachedID = CachedID::new(); CACHE.get(|| env.unwrap_or(JVm::singleton(None)?.env()?).find_class(MY_INTERFACE_NAME)) } fn bar(&self, env: &JEnv) -> Option<()> { static CACHE: CachedID = CachedID::new(); CACHE .get(|| Self::MyInterface_class(Some(env))?.method(env, b"bar\0", b"()V\0"))? .call(env, self.as_ref(), ()) } } pub struct MyInterfaceObject { inner: JObject, } impl MyInterface for MyInterfaceObject {} impl AsRef for MyInterfaceObject { fn as_ref(&self) -> &JObject { &self.inner } } #[no_mangle] #[allow(non_snake_case)] extern "system" fn Java_Hello_print(env: &JEnv, hello: &Hello, i: JInt) { println!("[Rust] Hello print called {i}"); hello.play(env); } #[no_mangle] #[allow(non_snake_case)] extern "system" fn Java_HelloOne_printone(env: &JEnv, hello: &Hello) { println!("[Rust] Hello printone called"); hello.play(env); hello.bar(env); } #[no_mangle] #[allow(non_snake_case)] extern "system" fn Java_HelloTwo_printtwo(env: &JEnv, hello: &Hello) { println!("[Rust] Hello printtwo called"); hello.play(env); hello.bar(env); } } mod world { use jnim::{CachedID, JClassID, JEnv, JInt, JNameMaker, JObject, JPlainMarker}; #[no_mangle] #[allow(non_snake_case)] extern "system" fn Java_World_print(env: &JEnv, world: &World, i: JInt) { println!("[Rust] World print called {i}"); world.play(env); world.get_state(env).map(|value| world.set_state(env, value + 100)); } struct World { __supper: JObject, } impl AsRef for World { fn as_ref(&self) -> &JObject { &self.__supper } } impl JNameMaker for World { const JAVA_PATH: &'static [u8] = b"World\0"; } impl JPlainMarker for World { fn class(env: Option<&JEnv>) -> Option { static CACHE: CachedID = CachedID::new(); CACHE.get(|| JEnv::env(env)?.find_class(Self::JAVA_PATH)) } } impl World { fn get_state(&self, env: &JEnv) -> Option { static CACHE: CachedID = CachedID::new(); CACHE .get(|| Self::class(Some(env))?.field(env, b"state\0", b"I\0"))? .get(env, self.as_ref()) } fn set_state(&self, env: &JEnv, value: JInt) -> Option<()> { static CACHE: CachedID = CachedID::new(); CACHE .get(|| Self::class(Some(env))?.field(env, b"state\0", b"I\0"))? .set(env, self.as_ref(), value) } fn play(&self, env: &JEnv) -> Option<()> { static CACHE: CachedID = CachedID::new(); CACHE .get(|| Self::class(Some(env))?.method(env, b"play\0", b"()V\0"))? .call(env, self.as_ref(), ()) } } } #[no_mangle] #[allow(non_snake_case)] extern "system" fn JNI_OnLoad(vm: JVm, _: &JVoid) -> JInt { JVm::singleton(Some(vm)); JVm::DEFAULT_VERSION }