jnat

A wrapper around the jni crate

29 releases (10 breaking)

0.11.2 Jul 31, 2023
0.10.2 Jul 27, 2023

29 downloads per month

MIT license

45KB
1K SLoC

jnat

A wrapper around the jni crate

View the documentation

Example

Create a new Cargo lib project with cargo new --lib mylib and add the following to Cargo.toml:

[dependencies]
jnat = [latest version]

[lib]
crate-type = ["cdylib"]

Add the following to src/lib.rs:

use jnat::{
  jnat_macros::jnat,
  jni::{objects::JClass, JNIEnv}, // jni crate, re-exported by jnat
  Class,
  Env,
  Signature,
  Type,
};

jnat!(HelloWorld, caller, (JNIEnv, JClass) -> ());

fn caller(env: JNIEnv, class: JClass) {
  let mut env = Env::new(&env);
  let class = Class::new(&mut env, class);

  class
    .call_static_method("hello", Signature::new(&[], Type::Void), &[])
    .unwrap();
}

Then, run cargo build. Create a new file called HelloWorld.java and add the following:

public class HelloWorld {
  private static native void caller();

  static {
    System.loadLibrary("mylib");
  }

  public static void main(String[] args) {
    HelloWorld.caller();
  }

  public static void hello() {
    System.out.println("Hello, world!");
  }
}

Compile the java file with javac -h . HelloWorld.java. Then, run java -Djava.library.path=path/to/target/debug HelloWorld. You should see Hello, world! printed to the console.

Notes

  • Jnat re-exports jni by default. If you want to use a different version of jni, you can disable either the default features or the jni feature.
  • Jnat exports a macro, jnat::jnat_macros::jnat (seen in the example above), which is used to generate the Java_HelloWorld_caller function. This macro can be disabled by disabling either the default features or the jni-macros feature. Note that the macro keeps the original function to prevent unintuitive behavior (so you can, in your Rust code, call just example() instead of Java_org_example_Class_example() while still allowing Java to call it).

Dependencies

~1–12MB
~83K SLoC