giovanniberti/robusta

Support for primitive arrays in combination with Signature

s1ck opened this issue · 1 comments

s1ck commented

Hey. I was wondering what the current approach is to mix structs annotated with #[derive(Signature)] where the impl needs to have a method that accepts e.g. jni's jlongarray. I thought I could fall back to using jni directly by passing &JNIEnv but that does not seem to work if the remaining arguments are jobject.

Is there a way to disable the signature resolution for certain functions of a struct? Thank you.

What I tried so far is:

pub extern "jni" fn dotProductArray<'env>(
    env: &'env JNIEnv,
    vector_a: LongArray<'env>,
    vector_b: LongArray<'env>,
) -> i64 {
    // Wrap the pointer to the java array into an AutoArray, which automatically
    // releases the pointer once the variable goes out of scope.
    super::dot_product(&vector_a.to_vec(env), &vector_b.to_vec(env))
}

and

#[repr(C)]
pub struct LongArray<'env>(JObject<'env>);

impl<'env> Signature for LongArray<'env> {
    const SIG_TYPE: &'static str = "[I)J";
}

impl<'env> JavaValue<'env> for LongArray<'env> {
    fn autobox(
        self,
        _env: &robusta_jni::jni::JNIEnv<'env>,
    ) -> robusta_jni::jni::objects::JObject<'env> {
        todo!()
    }

    fn unbox(
        s: robusta_jni::jni::objects::JObject<'env>,
        _env: &robusta_jni::jni::JNIEnv<'env>,
    ) -> Self {
        Self(s)
    }
}

impl<'env> LongArray<'env> {
    fn to_vec(&'env self, env: &'env JNIEnv) -> Vec<i64> {
        let len = env.get_array_length(self.0.into_inner()).unwrap();
        println!("len = {len}");
        let mut vec = vec![0; len as usize];
        let _ = env.get_long_array_region(self.0.into_inner(), 0, &mut vec);
        println!("vec = {vec:?}");
        vec
    }
}

This works, however, I actually would like to avoid allocating a Vec. Do you have a suggestion?

Maybe it would make sense to re-export https://docs.rs/jni/latest/jni/struct.JNIEnv.html#method.get_long_array_elements as well?

Also, would it be an option to separate the unbox and autobox into different traits, and only allow the unbox in the argument position and autobox for return types?

Hi and thanks for the issue!
There is an old PR that's about to be merged (#7) that addresses this exact issue, you can see here what the resulting interface will be.

If you do have time to experiment could you also try using this branch and see if everything is working as you expected? I'd really appreciate that 🙂

Also sorry for the long wait 😃