#[cfg(feature = "jvm-callback-support")]
use alloc::boxed::Box;
use core::ffi::c_void;
#[cfg(feature = "jvm-callback-support")]
use jni::{
errors::{Result, ThrowRuntimeExAndDefault},
objects::{Global, JObject},
sys::jlong,
EnvUnowned,
};
#[repr(C)]
pub struct DiplomatCallback<ReturnType> {
pub data: *mut c_void,
pub run_callback: unsafe extern "C" fn(*mut c_void, ...) -> ReturnType,
pub destructor: Option<unsafe extern "C" fn(*mut c_void)>,
}
impl<ReturnType> Drop for DiplomatCallback<ReturnType> {
fn drop(&mut self) {
if let Some(destructor) = self.destructor {
unsafe {
(destructor)(self.data);
}
}
}
}
#[cfg(feature = "jvm-callback-support")]
#[no_mangle]
extern "system" fn create_rust_jvm_cookie<'local>(
mut env: EnvUnowned<'local>,
obj_to_ref: JObject<'local>,
) -> jlong {
env.with_env(|env| -> Result<jlong> {
let global_ref = env.new_global_ref(obj_to_ref).unwrap();
Ok(Box::into_raw(Box::new(global_ref)) as jlong)
})
.resolve::<ThrowRuntimeExAndDefault>()
}
#[cfg(feature = "jvm-callback-support")]
#[no_mangle]
extern "system" fn destroy_rust_jvm_cookie(global_ref_boxed: jlong) {
unsafe {
drop(Box::from_raw(global_ref_boxed as *mut Global<JObject>));
}
}