# j4rs-java-call-rust
**Repository Path**: WalkingWithASnail/j4rs-java-call-rust
## Basic Information
- **Project Name**: j4rs-java-call-rust
- **Description**: https://github.com/astonbitecode/j4rs-java-call-rust
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2021-11-11
- **Last Updated**: 2022-10-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# j4rs-java-call-rust
## Java -> Rust direction examples
[j4rs](https://github.com/astonbitecode/j4rs) focused solely in facilitating Rust applications in making calls to Java code
by [allowing](https://github.com/astonbitecode/j4rs#basics)
JVM creation and manipulation from the Rust code,
efortless Java method invocations,
Java libraries [provisioning via Maven](https://github.com/astonbitecode/j4rs#Using-Maven-artifacts)
and [more](https://github.com/astonbitecode/j4rs#features).
This has changed since release 0.12.0.
***j4rs can now be used as well in Java projects that want to achieve JNI calls to Rust libraries.***
The repository contains two projects: One with Java code (using Maven) and one with Rust code (using Cargo).
*Note: For the commands execution, it is assumed that the repository
is cloned in a directory `/home/myuser/j4rs-java-call-rust`*
## Rust code
### Cargo.toml
The important things here are to add the two needed dependencies (`j4rs` and `j4rs_derive`)
and mark the project as a `cdylib`, in order to have a shared library as output.
This library will be loaded and used by the Java code.
### lib.rs
All the functions that we want to be callable from the Java code need to be annotated with the `call_from_java` attribute.
E.g.:
```rust
#[call_from_java("io.github.astonbitecode.j4rs.example.RustSimpleFunctionCall.fnnoargs")]
fn my_function_with_no_args() {
println!("Hello from the Rust world!");
}
```
The code above, will accept calls from a native method called `fnnoargs`,
defined in the Java class `io.github.astonbitecode.j4rs.example.RustSimpleFunctionCall`.
The `call_from_java` attribute contains the name of the native method as it is defined in Java, along with the package and the Class itself.
### Build the code
While in the */home/myuser/j4rs-java-call-rust/rust* directory, execute `cargo build`. When the compilation completes,
you should have the `librustlib.so` library under */home/myuser/j4rs-java-call-rust/rust/target/debug/*
## Java code
### pom.xml
We need the `j4rs` 0.12.0 dependency:
```xml
io.github.astonbitecode
j4rs
0.12.0
```
### Define the native functions
The [RustSimpleFunctionCall](https://github.com/astonbitecode/j4rs-java-call-rust/blob/master/java/src/main/java/io/github/astonbitecode/j4rs/example/RustSimpleFunctionCall.java)
and [RustFunctionCalls](https://github.com/astonbitecode/j4rs-java-call-rust/blob/master/java/src/main/java/io/github/astonbitecode/j4rs/example/RustFunctionCalls.java) classes
are examples for loading the shared library generated by Rust and defining the native functions.
Loading is done with:
```java
static {
System.loadLibrary("rustlib");
}
```
The native functions are defined simply like following:
```java
private static native void fnnoargs();
private static native void fnstringarg(Instance s);
```
`fnnoargs` in Java maps to `my_function_with_no_args` in Rust.
`fnstringarg` in Java maps to `my_function_with_1_string_arg`
More details on conventions that are in place [here](#Conventions).
### Main class
Simply define a main entry point that instantiates the class that loads the native functions.
### Build and execute
While in the */home/myuser/j4rs-java-call-rust/java* directory, execute `mvn install`. When the compilation completes,
you should have the `java-calls-rust-1.0-SNAPSHOT.jar` under */home/myuser/j4rs-java-call-rust/java/target/*
Execute the Main application `cd`ing to */home/myuser/j4rs-java-call-rust/java/target/* and by issuing:
```shell script
java -Djava.library.path=/home/myuser/j4rs-java-call-rust/rust/target/debug -cp java-calls-rust-1.0-SNAPSHOT.jar io.github.astonbitecode.j4rs.example.Main
```
`-Djava.library.path` VM option definition is needed in order for the JVM to locate the `mylib` shared library that is generated by Rust.
The output of the execution should be:
```
Welcome. This is a simple example that demonstrates calls to rust functions using j4rs.
Hello from the Rust world!
Bye!
```
## Conventions
`j4rs` implies some conventions for the arguments and the return types of the native functions.
### Native arguments
In the Rust world, the functions that are accessible from Java must be annotated with the `call_from_java` attribute.
They can have any number of arguments, but their type must be [j4rs::Instance](https://docs.rs/j4rs/0.12.0/j4rs/struct.Instance.html).
As always, the transformation of `Instance`s to rust values,
can be achieved with a call to `Jvm.to_rust`:
```rust
let s: String = jvm.to_rust(string_instance)?;
let s: i32 = jvm.to_rust(integer_instance)?;
```
In the Java world, the native methods can have any number of arguments again
and they must be of type `Instance`.
A Instance object can be created for any Java Object,
using the `Java2RustUtils.createInstance` method:
```java
var integerNativeInvocation = Java2RustUtils.createInstance(1);
var stringNativeInvocation = Java2RustUtils.createInstance("My String");
var anObjectNativeInvocation = Java2RustUtils.createInstance(new AnObject());
```
In other words the `j4rs::Instance` type in Rust,
maps to the `org.astonbitecode.j4rs.api.Instance` type in Java.
### Return types
In the Rust world, the return type of functions can be either `void`, or a `Result` of Instance.
The `Instances` can be created from an [InvocationArg](https://docs.rs/j4rs/0.12.0/j4rs/enum.InvocationArg.html),
like following:
```rust
let ia1 = InvocationArg::try_from("a str")?; // Creates an arg of java.lang.String
let i1 = Instance::try_from(ia1)? // Creates an Instance for the ia1 InvocationArg
let ia2 = InvocationArg::try_from(1_i64)?; // Creates an arg of java.lang.Long
let i2 = Instance::try_from(ia2)? // Creates an Instance for the ia1 InvocationArg
```
and be returned to the Java world.
In the Java world, the return type can be either `void` or `Instance`.
In the case that the Rust function returns an `Err`, an `InvocationException` will be thrown in the Java world.
Again, the `j4rs::Instance` type in Rust, maps to the `org.astonbitecode.j4rs.api.Instance` type in Java.