2 votes

Rust JNI async callback avec Tokio et Reqwest pour Android

Je teste Rust avec JNI asynchrone l'exécution. Je veux exécuter des requêtes en Rust et renvoyer le résultat à Android de manière asynchrone avec un callback. Je teste le code pour exécuter la requête en ligne de commande et cela fonctionne bien.

C'est ainsi que cela fonctionne en ligne de commande :

Rappel frappé :

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(())
}

Et la partie 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);
    }

Et la méthode 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);
}

L'erreur à laquelle je suis confronté :

  • JNI ENV env non-constant value :

    let response = env.new_string(&name).expect("Couldn't create java string!"); | ^^^ non-constant value

  • callback - 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

J'ai vérifié comment cela fonctionne, mais l'exemple semble être périmé : * https://github.com/mozilla/rust-Android-gradle/blob/master/samples/rust/src/lib.rs

1voto

CVS Points 295

J'ai résolu mon problème avec l'utilisation de l'option https://github.com/Dushistov/rust_swig Après l'avoir intégré, il générera automatiquement du code et vous pourrez vérifier comment il procède.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X