blob: 68604edb6aa94aa74c731ed08ec778150b822353 [file] [log] [blame]
// 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
}
}
};
}