【问题标题】:Rust JNI async callback with Tokio and Reqwest for AndroidRust JNI 异步回调与 Tokio 和 Reqwest for Android
【发布时间】:2020-04-15 02:59:46
【问题描述】:

我正在测试 Rust 与 JNI 异步 执行。我想在 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);
    }
}

东京/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);
    }

和口袋妖怪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 env non-constant value:
let response = env.new_string(&name).expect("Couldn't create java string!");
   |                        ^^^ non-constant value

  • 回调 - doesn't have a size known at compile-time:
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

【问题讨论】:

标签: android rust java-native-interface rust-tokio reqwest


【解决方案1】:

我解决了使用 https://github.com/Dushistov/rust_swig 的问题 集成后,它将自动生成代码,您可以检查它是如何工作的。

【讨论】: