| // A JNI call that is expected to return a non-null pointer when successful. |
| // If a null pointer is returned, it is converted to an Err. |
| // Returns Err if there is a pending exception after the call. |
| macro_rules! jni_non_null_call { |
| ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({ |
| let res = jni_non_void_call!($jnienv, $name $(, $args)*); |
| non_null!(res, concat!(stringify!($name), " result")) |
| }) |
| } |
| |
| // A non-void JNI call. May return anything — primitives, references, error codes. |
| // Returns Err if there is a pending exception after the call. |
| macro_rules! jni_non_void_call { |
| ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({ |
| log::trace!("calling checked jni method: {}", stringify!($name)); |
| |
| #[allow(unused_unsafe)] |
| let res = unsafe { |
| jni_method!($jnienv, $name)($jnienv, $($args),*) |
| }; |
| |
| check_exception!($jnienv); |
| res |
| }) |
| } |
| |
| macro_rules! non_null { |
| ( $obj:expr, $ctx:expr ) => { |
| if $obj.is_null() { |
| return Err($crate::errors::Error::NullPtr($ctx)); |
| } else { |
| $obj |
| } |
| }; |
| } |
| |
| // A void JNI call. |
| // Returns Err if there is a pending exception after the call. |
| macro_rules! jni_void_call { |
| ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({ |
| log::trace!("calling checked jni method: {}", stringify!($name)); |
| |
| #[allow(unused_unsafe)] |
| unsafe { |
| jni_method!($jnienv, $name)($jnienv, $($args),*) |
| }; |
| |
| check_exception!($jnienv); |
| }) |
| } |
| |
| // A JNI call that does not check for exceptions or verify |
| // error codes (if any). |
| macro_rules! jni_unchecked { |
| ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({ |
| log::trace!("calling unchecked jni method: {}", stringify!($name)); |
| |
| #[allow(unused_unsafe)] |
| unsafe { |
| jni_method!($jnienv, $name)($jnienv, $($args),*) |
| } |
| }) |
| } |
| |
| macro_rules! jni_method { |
| ( $jnienv:expr, $name:tt ) => {{ |
| log::trace!("looking up jni method {}", stringify!($name)); |
| let env = $jnienv; |
| match deref!(deref!(env, "JNIEnv"), "*JNIEnv").$name { |
| Some(method) => { |
| log::trace!("found jni method"); |
| method |
| } |
| None => { |
| log::trace!("jnienv method not defined, returning error"); |
| return Err($crate::errors::Error::JNIEnvMethodNotFound(stringify!( |
| $name |
| ))); |
| } |
| } |
| }}; |
| } |
| |
| macro_rules! check_exception { |
| ( $jnienv:expr ) => { |
| log::trace!("checking for exception"); |
| let check = { jni_unchecked!($jnienv, ExceptionCheck) } == $crate::sys::JNI_TRUE; |
| if check { |
| log::trace!("exception found, returning error"); |
| return Err($crate::errors::Error::JavaException); |
| } |
| log::trace!("no exception found"); |
| }; |
| } |
| |
| macro_rules! catch { |
| ( move $b:block ) => { |
| (move || $b)() |
| }; |
| ( $b:block ) => { |
| (|| $b)() |
| }; |
| } |
| |
| macro_rules! java_vm_unchecked { |
| ( $java_vm:expr, $name:tt $(, $args:expr )* ) => ({ |
| log::trace!("calling unchecked JavaVM method: {}", stringify!($name)); |
| java_vm_method!($java_vm, $name)($java_vm, $($args),*) |
| }) |
| } |
| |
| macro_rules! java_vm_method { |
| ( $jnienv:expr, $name:tt ) => {{ |
| log::trace!("looking up JavaVM method {}", stringify!($name)); |
| let env = $jnienv; |
| match deref!(deref!(env, "JavaVM"), "*JavaVM").$name { |
| Some(meth) => { |
| log::trace!("found JavaVM method"); |
| meth |
| } |
| None => { |
| log::trace!("JavaVM method not defined, returning error"); |
| return Err($crate::errors::Error::JavaVMMethodNotFound(stringify!( |
| $name |
| ))); |
| } |
| } |
| }}; |
| } |
| |
| macro_rules! deref { |
| ( $obj:expr, $ctx:expr ) => { |
| if $obj.is_null() { |
| return Err($crate::errors::Error::NullDeref($ctx)); |
| } else { |
| #[allow(unused_unsafe)] |
| unsafe { |
| *$obj |
| } |
| } |
| }; |
| } |