• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #[cfg(feature = "jvm-callback-support")]
2 use alloc::boxed::Box;
3 use core::ffi::c_void;
4 #[cfg(feature = "jvm-callback-support")]
5 use jni::{
6     objects::{GlobalRef, JObject},
7     sys::jlong,
8     JNIEnv,
9 };
10 
11 // struct representing a callback from Rust into a foreign language
12 // TODO restrict the return type?
13 #[repr(C)]
14 pub struct DiplomatCallback<ReturnType> {
15     // any data required to run the callback; e.g. a pointer to the
16     // callback wrapper object in the foreign runtime + the runtime itself
17     pub data: *mut c_void,
18     // function to actually run the callback
19     pub run_callback: unsafe extern "C" fn(*const c_void, ...) -> ReturnType,
20     // function to destroy this callback struct
21     pub destructor: Option<unsafe extern "C" fn(*const c_void)>,
22 }
23 
24 impl<ReturnType> Drop for DiplomatCallback<ReturnType> {
drop(&mut self)25     fn drop(&mut self) {
26         if let Some(destructor) = self.destructor {
27             unsafe {
28                 (destructor)(self.data);
29             }
30         }
31     }
32 }
33 
34 // return a pointer to a JNI GlobalRef, which is a JVM GC root to the object provided.
35 // this can then be stored as a field in a struct, so that the struct
36 // is not deallocated until the JVM calls a destructor that unwraps
37 // the GlobalRef so it can be dropped.
38 #[cfg(feature = "jvm-callback-support")]
39 #[no_mangle]
create_rust_jvm_cookie<'local>( env: JNIEnv<'local>, obj_to_ref: JObject<'local>, ) -> jlong40 extern "system" fn create_rust_jvm_cookie<'local>(
41     env: JNIEnv<'local>,
42     obj_to_ref: JObject<'local>,
43 ) -> jlong {
44     let global_ref = env.new_global_ref(obj_to_ref).unwrap();
45     Box::into_raw(Box::new(global_ref)) as jlong
46 }
47 
48 #[cfg(feature = "jvm-callback-support")]
49 #[no_mangle]
destroy_rust_jvm_cookie(global_ref_boxed: jlong)50 extern "system" fn destroy_rust_jvm_cookie(global_ref_boxed: jlong) {
51     unsafe {
52         drop(Box::from_raw(global_ref_boxed as *mut GlobalRef));
53     }
54 }
55