1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
use std::marker::PhantomData;
use jni_sys::*;
use crate::{Env, Global, Local, Ref, ReferenceType};
/// FFI: Use **Arg\<java::lang::Object\>** instead of jobject. This represents a (null?) function argument.
///
/// Unlike most Java reference types from this library, this *can* be null.
///
/// FFI safe where a jobject is safe, assuming you match your types correctly. Using the wrong type may result in
/// soundness issues, but at least on Android mostly seems to just result in JNI aborting execution for the current
/// process when calling methods on an instance of the wrong type.
#[repr(transparent)]
pub struct Arg<T: ReferenceType> {
object: jobject,
_class: PhantomData<T>,
}
impl<T: ReferenceType> Arg<T> {
/// **unsafe**: There's no guarantee the jobject being passed is valid or null, nor any means of checking it.
pub unsafe fn from_raw(object: jobject) -> Self {
Self {
object,
_class: PhantomData,
}
}
pub fn as_raw(&self) -> jobject {
self.object
}
/// **unsafe**: This assumes the argument belongs to the given Env/VM, which is technically unsound. However, the
/// intended use case of immediately converting any Arg s into ArgRef s at the start of a JNI callback,
/// where Java directly invoked your function with an Env + arguments, is sound.
pub unsafe fn into_ref<'env>(self, env: Env<'env>) -> Option<Ref<'env, T>> {
if self.object.is_null() {
None
} else {
Some(Ref::from_raw(env, self.object))
}
}
/// **unsafe**: This assumes the argument belongs to the given Env/VM, which is technically unsound. However, the
/// intended use case of immediately converting any Arg s into ArgRef s at the start of a JNI callback,
/// where Java directly invoked your function with an Env + arguments, is sound.
pub unsafe fn into_local<'env>(self, env: Env<'env>) -> Option<Local<'env, T>> {
if self.object.is_null() {
None
} else {
Some(Local::from_raw(env, self.object))
}
}
/// **unsafe**: This assumes the argument belongs to the given Env/VM, which is technically unsound. However, the
/// intended use case of immediately converting any Arg s into ArgRef s at the start of a JNI callback,
/// where Java directly invoked your function with an Env + arguments, is sound.
pub unsafe fn into_global(self, env: Env) -> Option<Global<T>> {
if self.object.is_null() {
None
} else {
let jnienv = env.as_raw();
let object = ((**jnienv).v1_2.NewGlobalRef)(jnienv, self.object);
Some(Global::from_raw(env.vm(), object))
}
}
}