Rust JNI异步回调使用Tokio和Reqwest在Android上

3

我正在测试使用JNI异步执行Rust。我想在Rust中执行请求并通过回调异步返回结果给Android。我正在测试在命令行中执行请求的代码,它能正常工作。

以下是在命令行中的工作方式:

回调结构:

struct Processor {
    pub(crate) callback: Box<dyn FnMut(String)>,
}

impl Processor {

    fn set_callback(&mut self, c: impl FnMut(String) + 'static) {
        self.callback = Box::new(c);
    }

    fn process_events(&mut self, result: String) {
        (self.callback)(result);
    }
}

Tokio/reqwest:

const DATA_URL: &str = "https://pokeapi.co/api/v2/pokemon/1/";

#[tokio::main]
pub async fn load_swapi_async_with_cb(callback: Box<dyn FnMut(String)>) -> Result<(), Box<dyn std::error::Error>> {
    println!("load_swload_swapi_async_with_cbapi_async started");
    let mut cb = Processor {
        callback: Box::new(callback),
    };
    let body = reqwest::get(DATA_URL)
        .await?
        .json::<HashMap<String, String>>()
        .await?;
    //println!("{:#?}", body);
    let name = match body.get("name") {
        Some(name) => name,
        None => "Failed to parse"
    }.to_string();

    println!("Name is: {} ", name);
    cb.process_events(name);
    Ok(())
}

并且 JNI 部分:

    #[no_mangle]
    #[allow(non_snake_case)]
    pub extern "C" fn Java_com_omg_app_greetings_MainActivity_callback(env: JNIEnv,
                                                                       _class: JClass,
                                                                       callback: JObject) {

        static callback: dyn FnMut(String) + 'static = |name| {
        let response = env.new_string(&name).expect("Couldn't create java string!");
            env.call_method(callback, "rustCallbackResult", "(Ljava/lang/String;)V",
                        &[JValue::from(JObject::from(response))]).unwrap();
        };

        pokemon_api(callback);
    }

关于 pokemon API 的方法:

#[no_mangle]
pub extern fn pokemon_api(callback: impl FnMut(String) + 'static) {
    let cb_box = Box::new(callback);
    swapi::load_swapi_async_with_cb(cb_box);
}

我遇到的错误:

  • JNI环境env非常量值
let response = env.new_string(&name).expect("Couldn't create java string!");
   |                        ^^^ non-constant value


回调函数 - 在编译时大小未知
static callback: dyn FnMut(String) + 'static = |name| {
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time

我在检查这个工作原理,但这个示例似乎已经过时: * https://github.com/mozilla/rust-android-gradle/blob/master/samples/rust/src/lib.rs


https://users.rust-lang.org/t/rust-jni-android-async-callback/41016 - ilbets
我对Rust不是很了解,但回调函数会在不同的线程中执行吗?每个JNIEnv*都绑定到创建它的线程,并且在不同的线程上使用JNIEnv是致命错误。幸运的是,您可以使用AttachCurrentThreadAsDaemon来获取有效的JNIEnv - Botje
我从未考虑过这个问题...让我更深入地调查一下。谢谢。 - ilbets
1个回答

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接