将具有生命周期的借用引用转换为 Rust 中的原始指针

Casting a borrowed reference with a lifetime to a raw pointer in Rust

我是 Rust 的新手,正在努力思考生命周期。请考虑以下代码:

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!
    }
}

JNIEnv::from_raw 方法的类型签名为 from_raw(ptr: *mut JNIEnv) -> Result<Self>,因此导致编译错误:

|         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>`

然后我尝试了 JNIEnv::from_raw(self._env as *mut JNIEnv<'a>).unwrap(),但这导致:

|         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!
|                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

如何从结构中的引用中获取有效的 JNIEnv?

干杯,感谢您的宝贵时间!

更新

这里有一个不那么做作的方法来演示这个问题。

pub fn create_camera_session(&'a mut self, surface: jobject) {
    // error!
    let window = ffi::ANativeWindow_fromSurface(self._env as *mut JNIEnv<'a>, surface);
}

这导致:

error[E0606]: casting `&'a jni::JNIEnv<'a>` as `*mut jni::JNIEnv<'a>` is invalid

ANativeWindow_fromSurface 的类型签名是 ANativeWindow_fromSurface(env: *mut JNIEnv, surface: jobject) -> *mut ANativeWindow

jni 箱子中有两种名为 JNIEnv 的类型:

  1. jni::sys::JNIEnv:这是一个类型别名:type JNIEnv = *const JNINativeInterface_;
  2. jni::JNIEnv:这是对 jni::sys::JNIEnv.
  3. 的安全包装

您不能简单地使用 as 在两者之间进行转换,因为它们是不相关的类型。事实上,在你的 env() 方法中,你可以直接克隆 self._env。此外,jni::JNIEnv 只是一个指针的包装器,克隆很便宜(它不是深拷贝),因此您可以按值而不是按引用存储它 self._env.

jni::JNIEnv 公开了在两种类型之间进行转换的方法。 jni::JNIEnv::from_raw goes from jni::sys::JNIEnv to jni::JNIEnv, and jni::JNIEnv::get_native_interface 反其道而行之。