diff --git a/java-spaghetti/src/lib.rs b/java-spaghetti/src/lib.rs index d6ae783..0a412d1 100644 --- a/java-spaghetti/src/lib.rs +++ b/java-spaghetti/src/lib.rs @@ -12,16 +12,17 @@ pub use ::jni_sys as sys; pub use ::std; mod refs { - mod arg; mod global; mod local; mod ref_; + mod return_; pub use arg::*; pub use global::*; pub use local::*; pub use ref_::*; + pub use return_::*; } mod array; diff --git a/java-spaghetti/src/refs/local.rs b/java-spaghetti/src/refs/local.rs index d855388..a020c78 100644 --- a/java-spaghetti/src/refs/local.rs +++ b/java-spaghetti/src/refs/local.rs @@ -3,7 +3,7 @@ use std::ops::Deref; use jni_sys::*; -use crate::{Env, Global, Ref, ReferenceType}; +use crate::{Env, Global, Ref, ReferenceType, Return}; /// A [Local](https://www.ibm.com/support/knowledgecenter/en/SSYKE2_8.0.0/com.ibm.java.vm.80.doc/docs/jni_refs.html), /// non-null, reference to a Java object (+ [Env]) limited to the current thread/stack. @@ -70,6 +70,16 @@ impl<'env, T: ReferenceType> Local<'env, T> { self.ref_ } + pub fn as_return(self) -> Return<'env, T> { + let env: *mut *const JNINativeInterface_ = self.env().as_raw(); + let object = unsafe { ((**env).v1_2.NewLocalRef)(env, self.as_raw()) }; + unsafe { Return::from_raw(object) } + } + + pub fn into_return(self) -> Return<'env, T> { + unsafe { Return::from_raw(self.into_raw()) } + } + pub fn cast(&self) -> Result, crate::CastError> { let env = self.env(); let jnienv = env.as_raw(); diff --git a/java-spaghetti/src/refs/return_.rs b/java-spaghetti/src/refs/return_.rs new file mode 100644 index 0000000..cdf9600 --- /dev/null +++ b/java-spaghetti/src/refs/return_.rs @@ -0,0 +1,37 @@ +use std::marker::PhantomData; +use std::ptr::null_mut; + +use jni_sys::jobject; + +use crate::ReferenceType; + +/// FFI: Use **Return\** instead of jobject. This represents a (null?) JNI function call return value. +/// +/// 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. +#[repr(transparent)] +pub struct Return<'env, T: ReferenceType> { + object: jobject, + _class: PhantomData<&'env T>, +} + +impl<'env, T: ReferenceType> Return<'env, T> { + pub unsafe fn from_raw(object: jobject) -> Self { + Self { + object, + _class: PhantomData, + } + } + + pub fn null() -> Self { + Self { + object: null_mut(), + _class: PhantomData, + } + } + + pub fn as_raw(&self) -> jobject { + self.object + } +}