#jni #java #java-class #ffi #proc-macro #extension

jnix

High-level extensions to help with the usage of JNI in Rust code

12 releases

0.5.1 Oct 24, 2023
0.5.0 Sep 16, 2022
0.4.0 Feb 18, 2021
0.3.0 Nov 27, 2020
0.1.0 Nov 22, 2019

#323 in Rust patterns

Download history 1770/week @ 2024-08-08 2038/week @ 2024-08-15 2363/week @ 2024-08-22 2319/week @ 2024-08-29 1876/week @ 2024-09-05 1151/week @ 2024-09-12 2133/week @ 2024-09-19 1001/week @ 2024-09-26 1043/week @ 2024-10-03 811/week @ 2024-10-10 1932/week @ 2024-10-17 1876/week @ 2024-10-24 1306/week @ 2024-10-31 1799/week @ 2024-11-07 1982/week @ 2024-11-14 1969/week @ 2024-11-21

7,440 downloads per month

Apache-2.0 OR MIT

35KB
675 lines

jnix

This crate provides high-level extensions to help with the usage of JNI in Rust code. Internally, it uses the jni-rs crate for the low-level JNI operations.

Some helper traits are provided, such as:

  • AsJValue: for allowing a JNI type to be convected to a JValue wrapper type.
  • IntoJava: for allowing a Rust type to be converted to a Java type.
  • FromJava: for allowing a Rust type to be created from a Java type.

A JnixEnv helper type is also provided, which is a JNIEnv wrapper that contains an internal class cache for preloaded classes.

If compiled with the derive feature flag, the crate also exports procedural macros to derive IntoJava and to derive FromJava, which makes writing conversion code a lot easier. An example would be:

use jnix::{
    jni::{objects::JObject, JNIEnv},
    JnixEnv, FromJava, IntoJava,
};

// Rust type definition
#[derive(Default, FromJava, IntoJava)]
#[jnix(package = "my.package")]
pub struct MyData {
    number: i32,
    string: String,
}

// A JNI function called from Java that creates a `MyData` Rust type, converts it to a Java
// type and returns it.
#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_my_package_JniClass_getData<'env>(
    env: JNIEnv<'env>,
    _this: JObject<'env>,
    data: JObject<'env>,
) -> JObject<'env> {
    // Create the `JnixEnv` wrapper
    let env = JnixEnv::from(env);

    // Convert parameter to Rust type
    let data = MyData::from_java(&env, data);

    // Create a new `MyData` object by converting from the Rust type. Since a smart pointer is
    // returned from `into_java`, the inner object must be "leaked" sothat the garbage collector
    // can own it afterwards
    data.into_java(&env).forget()
}
package my.package;

public class MyData {
    public MyData(int number, String string) {
        // This is the constructor that is called by the generated `IntoJava` code
        //
        // Note that the fields don't actually have to exist, the only thing that's necessary
        // is for the target Java class to have a constructor with the expected type signature
        // following the field order of the Rust type.
    }

    // These getters are called by the generated `FromJava` code
    public int getNumber() {
        return 10;
    }

    public String getString() {
        return "string value";
    }
}

License: Apache-2.0 OR MIT

Dependencies

~1.6–7.5MB
~55K SLoC