Я слежу за кастингом заимствованная ссылка со временем жизни на необработанный указатель в Rust, которая решила неправильную проблему.
Обратите внимание на следующий код:
extern crate jni;
extern crate ffi;
use jni::JNIEnv;
use jni::objects::JClass;
use jni::sys::{jint, jlong, jobject};
struct CameraAppEngine {
_env: *mut jni::sys::JNIEnv,
_width: i32,
_height: i32
}
impl CameraAppEngine {
pub fn new(_env: *mut jni::sys::JNIEnv, _width: i32, _height: i32) -> CameraAppEngine {
CameraAppEngine { _env, _width, _height }
}
pub fn create_camera_session(&mut self, surface: jobject) {
// error!
let window = ffi::ANativeWindow_fromSurface(self._env, surface);
}
}
fn app_engine_create(env: &JNIEnv, width: i32, height: i32) -> *mut CameraAppEngine {
let engine = CameraAppEngine::new(env.get_native_interface(), width, height);
Box::into_raw(Box::new(engine))
}
#[no_mangle]
pub extern "C" fn Java_io_waweb_cartoonifyit_MainActivity_createCamera(env: JNIEnv<'static>, _: JClass, width:jint, height:jint) -> jlong {
app_engine_create(&env, width, height) as jlong
}
#[no_mangle]
pub extern "C" fn Java_io_waweb_cartoonifyit_MainActivity_onPreviewSurfaceCreated(_: JNIEnv, _: JClass, engine_ptr:jlong, surface:jobject) {
let mut app = unsafe { Box::from_raw(engine_ptr as *mut CameraAppEngine) };
app.create_camera_session(surface);
}
А в ffi
обрешетке у нас есть:
extern "C" {
pub fn ANativeWindow_fromSurface(env: *mut JNIEnv, surface: jobject) -> *mut ANativeWindow;
}
Это приводит к:
error[E0308]: mismatched types
--> native_app/src/lib.rs:24:53
|
| let window = ffi::ANativeWindow_fromSurface(self._env, surface);
| ^^^^^^^^^ expected struct `ffi::JNINativeInterface`, found struct `jni::sys::JNINativeInterface_`
|
= note: expected raw pointer `*mut *const ffi::JNINativeInterface`
found raw pointer `*mut *const jni::sys::JNINativeInterface_`
error[E0308]: mismatched types
--> native_app/src/lib.rs:24:64
|
| let window = ffi::ANativeWindow_fromSurface(self._env, surface);
| ^^^^^^^ expected enum `std::ffi::c_void`, found enum `jni::sys::_jobject`
|
= note: expected raw pointer `*mut std::ffi::c_void`
found raw pointer `*mut jni::sys::_jobject`
Проблема в том, что тип JNIEnv, ожидаемый ANativeWindow_fromSurface
, на самом деле не связан с jni::sys::JNIEnv
полностью.
Это определено в ffi
так:
pub type JNIEnv = *const JNINativeInterface;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct JNINativeInterface {
pub reserved0: *mut ::std::os::raw::c_void,
pub reserved1: *mut ::std::os::raw::c_void,
pub reserved2: *mut ::std::os::raw::c_void,
pub reserved3: *mut ::std::os::raw::c_void,
pub GetVersion: ::std::option::Option<unsafe extern "C" fn(arg1: *mut JNIEnv) -> jint>,
pub DefineClass: ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut JNIEnv,
arg2: *const ::std::os::raw::c_char,
arg3: jobject,
arg4: *const jbyte,
arg5: jsize,
) -> jclass,
>,
pub FindClass: ::std::option::Option<
unsafe extern "C" fn(arg1: *mut JNIEnv, arg2: *const ::std::os::raw::c_char) -> jclass,
>,
pub FromReflectedMethod:
::std::option::Option<unsafe extern "C" fn(arg1: *mut JNIEnv, arg2: jobject) -> jmethodID>,
pub FromReflectedField:
::std::option::Option<unsafe extern "C" fn(arg1: *mut JNIEnv, arg2: jobject) -> jfieldID>,
pub ToReflectedMethod: ::std::option::Option<
unsafe extern "C" fn(
arg1: *mut JNIEnv,
arg2: jclass,
arg3: jmethodID,
arg4: jboolean,
) -> jobject,
>
// etc...
}
Учитывая код клея, показанный в примере, как мне получить действительную ссылку на ffi::JNIEnv
, чтобы я мог передать ее методу ANativeWindow_fromSurface
. Бонусные баллы, если вы дадите совет по преобразованию jni::sys::jobject
в *mut std::os::raw::c_void
(проблемы со сроком службы, нулевые указатели и т. Д.).
ffi::JNINativeInterface
иjni::sys::JNINativeInterface_
- это одна и та же структура, и поэтому вы должны иметь возможность выполнять приведение между ними, не вызывая ошибок сегментации. Однако мне любопытно, почему вы вообще используете ящик jni? Получается, что в ffi есть все нужные вам типы? Наконец, ящик jni не предназначен для использования с android afaik. - person PiRocks   schedule 16.02.2020jni
ящик. Это то, что использовалось во всех примерах, показывающих взаимодействие android / rust. EGJava_io_waweb_cartoonifyit_MainActivity_createCamera
автоматически получает JNIEnv. Возможно, я попробую изменить этот тип на ffi :: JniEnv и посмотреть, что будет. Спасибо за совет! - person drkstr101   schedule 16.02.2020