android(kotlin / java)列表<String> /array<String>->使用jni<String>使用rustvec

问题描述 投票:0回答:1

我有一个Android应用(用Kotlin编写),并在Rust中运行处理代码。我正在尝试将

List<String>
数据发送到Rust后端,并将其解释为
Vec<String>
。列表的大小是可变的。我正在使用JNI(Java本机界面)。

android(kotlin)

在Kotlin端I具有以下功能签名:

package eu.mypackage.rust class SomeName { @Throws(IllegalArgumentException::class) external fun checkAnswer(answerInput: String, answerList: List<String>): Boolean }
我打电话给以下哪个:

val isCorrect = sn.checkAnswer(answerInput, answerList)

rust

在生锈方面,我拥有此草稿功能:

#[cfg(target_os = "android")] #[allow(non_snake_case)] pub mod android { extern crate jni; // This is the interface to the JVM that we'll call the majority of our methods on. // @See https://docs.rs/jni/latest/jni/ use self::jni::JNIEnv; // These objects are what you should use as arguments to your native function. // They carry extra lifetime information to prevent them escaping this context // and getting used after being GC'd. use self::jni::objects::{JClass, JString, JObject, JObjectArray}; // Not sure what is required // This is just a pointer. We'll be returning it from our function. // We can't return one of the objects with lifetime information // because the lifetime checker won't let us. use self::jni::sys::{jstring, jboolean, jobjectArray, jsize}; // Not sure what is required fn kotlin_list_to_rust_vec_string(env: &JNIEnv, java_array: &jobjectArray) -> Vec<String> { // TODO function to convert } #[no_mangle] // This keeps Rust from "mangling" the name so it is unique (crate). pub extern "system" fn Java_eu_surafusoft_rust_KanjiOrigin_checkAnswer<'local>( // NOTE: createDatabase, not create_database (gives issues in Kotlin) mut env: JNIEnv<'local>, // This is the class that owns our static method. It's not going to be used, // but still must be present to match the expected signature of a static native method. _class: JClass<'local>, answerInput: JString<'local>, answerList: JObjectArray<'local>, // JObjectArray correct? ) -> jboolean // Keep in mind that arrays of jboolean values should only ever hold values of 0 or 1 because any other value could lead to undefined behaviour within the JVM. // https://docs.rs/jni/latest/jni/struct.JNIEnv.html#jboolean-elements { let answer_input: String = env.get_string(&answerInput).expect("Couldn't get java string!").into(); let answer_list = kotlin_list_to_rust_vec_string(&env, &answerList); // ... code to process answer_list return 1 // true or 0 for false } }

问题

java

List<String>
    -> rust
  1. Vec<String>
    似乎没有直接的转换,因此需要像
    kotlin_list_to_rust_vec_string
    的函数?
    应该在
  2. kotlin_list_to_rust_vec_string
  3. 中有什么代码?我认为
    env
    answerList
    应该是避免拧紧Kotlin侧数据的参考? (数据量很小,因此复制数据的数量很好)
    
        
java android kotlin rust java-native-interface
1个回答
0
投票

在LLM的帮助下,我能够产生以下解决方案:

fn kotlin_list_to_rust_vec_string(env: &mut JNIEnv, java_array: &JObjectArray) -> Vec<String> { let string_count = env.get_array_length(java_array).unwrap(); let mut rust_strings = Vec::with_capacity(string_count as usize); for i in 0..string_count { let string_element = env.get_object_array_element(&java_array, i).unwrap(); let java_string: JString = string_element.into(); let rust_string = env.get_string(&java_string).unwrap().into(); rust_strings.push(rust_string); } rust_strings }

env

变量必须可变才能工作(不确定这是否是一种安全的方法吗?),请使用以下方式调用函数:

let answer_list = kotlin_list_to_rust_vec_string(&mut env, &answerList);

android(kotlin)

当锈蚀侧编译的代码时,我的Android应用程序崩溃了错误:

java_vm_ext.cc:598] JNI DETECTED ERROR IN APPLICATION: jarray argument has non-array type: java.util.ArrayList java_vm_ext.cc:598] in call to GetArrayLength java_vm_ext.cc:598] from boolean eu.mypackage.rust.

llm解释了错误:

在kotlin中,当您将

List<String>
传递给本机方法时,它仍然是一个

java.util.ArrayList

,这不是与JNI兼容的数组。
解决方案:将其转换为
List<String>
之前将其转换为rust
SO更新功能签名:
String[]

并在我的功能调用中添加

@Throws(IllegalArgumentException::class) // in Kotlin, when you pass a List<String> to a native method, it remains a java.util.ArrayList, // which is not a JNI-compatible array. Convert the List<String> to a String[] external fun checkAnswer(answerInput: String, answerList: Array<String>): Boolean // List<String>

.toTypedArray()

解决了最后一个问题。
提出问题

确定LLM是否正确,实际上是JNI不支持
val isCorrect = sn.checkAnswer(answerInput, answerList.toTypedArray())  // convert to Array
? 这确实是做事的最好方法吗?

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.