Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for primitive arrays in combination with Signature #16

Open
s1ck opened this issue Dec 4, 2022 · 1 comment
Open

Support for primitive arrays in combination with Signature #16

s1ck opened this issue Dec 4, 2022 · 1 comment

Comments

@s1ck
Copy link

s1ck commented Dec 4, 2022

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?

@giovanniberti
Copy link
Owner

giovanniberti commented Dec 22, 2022

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 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants