I am new to rust and am trying to wrap my head around lifetimes. Please consider the following code:
use jni::JNIEnv;
pub struct CameraAppEngine<'a> {
_env: &'a JNIEnv<'a>,
_width: i32,
_height: i32
}
impl<'a> CameraAppEngine<'a> {
pub fn new(_env: &'a JNIEnv<'a>, _width: i32, _height: i32) -> CameraAppEngine {
CameraAppEngine { _env, _width, _height }
}
pub fn env(&'a self) -> JNIEnv<'a> {
JNIEnv::from_raw(self._env).unwrap() // error!
}
}
The JNIEnv::from_raw method has a type signature of from_raw(ptr: *mut JNIEnv) -> Result<Self>
, so this results in the compile error:
| JNIEnv::from_raw(self._env).unwrap()
| ^^^^^^^^^ types differ in mutability
|
= note: expected raw pointer `*mut *const jni::sys::JNINativeInterface_`
found reference `&'a jni::JNIEnv<'a>`
I then tried JNIEnv::from_raw(self._env as *mut JNIEnv<'a>).unwrap()
, but this results in:
| JNIEnv::from_raw(self._env as *mut JNIEnv<'a>).unwrap() // error!
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected *-ptr, found struct `jni::JNIEnv`
|
= note: expected raw pointer `*mut *const jni::sys::JNINativeInterface_`
found raw pointer `*mut jni::JNIEnv<'a>`
error[E0606]: casting `&'a jni::JNIEnv<'a>` as `*mut jni::JNIEnv<'a>` is invalid
--> native_app/src/camera_engine.rs:16:26
|
| JNIEnv::from_raw(self._env as *mut JNIEnv<'a>).unwrap() // error!
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How do I get a valid JNIEnv out of the reference in the struct?
Cheers and thank you for your time!
Update
Here is a less contrived way to demonstrate the prolem.
pub fn create_camera_session(&'a mut self, surface: jobject) {
// error!
let window = ffi::ANativeWindow_fromSurface(self._env as *mut JNIEnv<'a>, surface);
}
This results in:
error[E0606]: casting `&'a jni::JNIEnv<'a>` as `*mut jni::JNIEnv<'a>` is invalid
The type signature of ANativeWindow_fromSurface is ANativeWindow_fromSurface(env: *mut JNIEnv, surface: jobject) -> *mut ANativeWindow
.
There are two types named JNIEnv
in the jni
crate:
jni::sys::JNIEnv
: This is a type alias: type JNIEnv = *const JNINativeInterface_;
jni::JNIEnv
: This is a safe wrapper around jni::sys::JNIEnv
.You cannot simply use as
to cast between the two, because they are unrelated types. In fact, in your env()
method, you can just clone self._env
. Furthermore, jni::JNIEnv
is just a wrapper for a pointer, and cloning is cheap (it's not a deep copy), so you can store it by value rather by reference in self._env
.
jni::JNIEnv
exposes methods to convert between the two types. jni::JNIEnv::from_raw
goes from jni::sys::JNIEnv
to jni::JNIEnv
, and jni::JNIEnv::get_native_interface
goes the other way.