Dushistov / flapigen-rs

Tool for connecting programs or libraries written in Rust with other languages
BSD 3-Clause "New" or "Revised" License
775 stars 59 forks source link

Is there a way to pass a byte array (byte[]) into a function? Vec<u8> and Vec<i8> produces errors. #439

Closed Kofituo closed 1 year ago

Kofituo commented 1 year ago

Here's the error: error: Do not know conversion from such rust type 'Vec < i8 >' to Java type

This works:

fn test() -> Vec<i8> {}

But this doesn't


fn test(t:Vec<i8>) {}
Dushistov commented 1 year ago

Working variant is &[i8] for both input and output argument. The explanation is simple: JNI require allocation in case of return type:

fn test() -> &[i8]

So return Vec<i8> is waste of CPU cycles, you allocate with Rust allocator, when you create Vec<i8>, because of then you need reallocate SetByteArrayRegion.

The same for input, this works:

fn test(t: &[i8])

but there are no direct conversation from jbyteArray to Vec<i8>, this is requires extra allocation, so in default set of type conversation there are only jbyteArray -> &[i8], which doesn't require extra allocations.

You can add such code into your java_glue.rs.in to get working Vec<i8> <- byte[] conversation:

foreign_typemap!(
    ($p:r_type) Vec<i8> <= jbyteArray {
        let jni_arr = JavaByteArray::new(env, $p);
        $out = jni_arr.to_slice().to_vec();
    };
    (f_type, unique_prefix = "/*Vec<i8>*/") <= "/*Vec<i8>*/byte []";
);
Kofituo commented 1 year ago

Okay thanks!