Приведение заимствованной ссылки со временем жизни к необработанному указателю в Rust - PullRequest
1 голос
/ 14 февраля 2020

Я новичок в ржавчине и пытаюсь обернуть мою жизнь. Пожалуйста, рассмотрите следующий код:

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.

1 Ответ

2 голосов
/ 15 февраля 2020

В ящике jni есть два типа с именем JNIEnv:

  1. jni::sys::JNIEnv: псевдоним типа: type JNIEnv = *const JNINativeInterface_;
  2. jni::JNIEnv: Это безопасная оболочка для jni::sys::JNIEnv.

Вы не можете просто использовать as для приведения между ними, потому что они не связаны между собой. Фактически, в вашем методе env() вы можете просто клонировать self._env. Кроме того, jni::JNIEnv - это просто оболочка для указателя, и клонирование дешево (это не глубокая копия), поэтому вы можете хранить его по значению, а не по ссылке в self._env.

jni::JNIEnv подвергает методы для преобразования между двумя типами. jni::JNIEnv::from_raw идет от jni::sys::JNIEnv до jni::JNIEnv, а jni::JNIEnv::get_native_interface идет в другую сторону.

...