• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // A JNI call that is expected to return a non-null pointer when successful.
2 // If a null pointer is returned, it is converted to an Err.
3 // Returns Err if there is a pending exception after the call.
4 macro_rules! jni_non_null_call {
5     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
6         let res = jni_non_void_call!($jnienv, $name $(, $args)*);
7         non_null!(res, concat!(stringify!($name), " result")).into()
8     })
9 }
10 
11 // A non-void JNI call. May return anything — primitives, references, error codes.
12 // Returns Err if there is a pending exception after the call.
13 macro_rules! jni_non_void_call {
14     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
15         log::trace!("calling checked jni method: {}", stringify!($name));
16 
17         let res = unsafe {
18             jni_method!($jnienv, $name)($jnienv, $($args),*)
19         };
20 
21         check_exception!($jnienv);
22         res
23     })
24 }
25 
26 macro_rules! non_null {
27     ( $obj:expr, $ctx:expr ) => {
28         if $obj.is_null() {
29             return Err($crate::errors::Error::NullPtr($ctx));
30         } else {
31             $obj
32         }
33     };
34 }
35 
36 // A void JNI call.
37 // Returns Err if there is a pending exception after the call.
38 macro_rules! jni_void_call {
39     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
40         log::trace!("calling checked jni method: {}", stringify!($name));
41 
42         unsafe {
43             jni_method!($jnienv, $name)($jnienv, $($args),*)
44         };
45 
46         check_exception!($jnienv);
47     })
48 }
49 
50 // A JNI call that does not check for exceptions or verify
51 // error codes (if any).
52 macro_rules! jni_unchecked {
53     ( $jnienv:expr, $name:tt $(, $args:expr )* ) => ({
54         log::trace!("calling unchecked jni method: {}", stringify!($name));
55 
56         unsafe {
57             jni_method!($jnienv, $name)($jnienv, $($args),*)
58         }
59     })
60 }
61 
62 macro_rules! jni_method {
63     ( $jnienv:expr, $name:tt ) => {{
64         log::trace!("looking up jni method {}", stringify!($name));
65         let env = $jnienv;
66         match deref!(deref!(env, "JNIEnv"), "*JNIEnv").$name {
67             Some(method) => {
68                 log::trace!("found jni method");
69                 method
70             }
71             None => {
72                 log::trace!("jnienv method not defined, returning error");
73                 return Err($crate::errors::Error::JNIEnvMethodNotFound(stringify!(
74                     $name
75                 )));
76             }
77         }
78     }};
79 }
80 
81 macro_rules! check_exception {
82     ( $jnienv:expr ) => {
83         log::trace!("checking for exception");
84         let check = { jni_unchecked!($jnienv, ExceptionCheck) } == $crate::sys::JNI_TRUE;
85         if check {
86             log::trace!("exception found, returning error");
87             return Err($crate::errors::Error::JavaException);
88         }
89         log::trace!("no exception found");
90     };
91 }
92 
93 macro_rules! catch {
94     ( move $b:block ) => {
95         (move || $b)()
96     };
97     ( $b:block ) => {
98         (|| $b)()
99     };
100 }
101 
102 macro_rules! java_vm_unchecked {
103     ( $java_vm:expr, $name:tt $(, $args:expr )* ) => ({
104         log::trace!("calling unchecked JavaVM method: {}", stringify!($name));
105         java_vm_method!($java_vm, $name)($java_vm, $($args),*)
106     })
107 }
108 
109 macro_rules! java_vm_method {
110     ( $jnienv:expr, $name:tt ) => {{
111         log::trace!("looking up JavaVM method {}", stringify!($name));
112         let env = $jnienv;
113         match deref!(deref!(env, "JavaVM"), "*JavaVM").$name {
114             Some(meth) => {
115                 log::trace!("found JavaVM method");
116                 meth
117             }
118             None => {
119                 log::trace!("JavaVM method not defined, returning error");
120                 return Err($crate::errors::Error::JavaVMMethodNotFound(stringify!(
121                     $name
122                 )));
123             }
124         }
125     }};
126 }
127 
128 macro_rules! deref {
129     ( $obj:expr, $ctx:expr ) => {
130         if $obj.is_null() {
131             return Err($crate::errors::Error::NullDeref($ctx));
132         } else {
133             #[allow(unused_unsafe)]
134             unsafe {
135                 *$obj
136             }
137         }
138     };
139 }
140