mirror of
https://github.com/hexedtech/jni-toolbox.git
synced 2024-11-25 00:44:53 +01:00
docs: updated README, minimal rustdocs
This commit is contained in:
parent
d6c0aa2f9e
commit
6f424dadf7
3 changed files with 40 additions and 32 deletions
57
README.md
57
README.md
|
@ -3,13 +3,12 @@
|
||||||
[![Crates.io Version](https://img.shields.io/crates/v/jni-toolbox)](https://crates.io/crates/jni-toolbox)
|
[![Crates.io Version](https://img.shields.io/crates/v/jni-toolbox)](https://crates.io/crates/jni-toolbox)
|
||||||
[![docs.rs](https://img.shields.io/docsrs/jni-toolbox)](https://docs.rs/jni-toolbox)
|
[![docs.rs](https://img.shields.io/docsrs/jni-toolbox)](https://docs.rs/jni-toolbox)
|
||||||
|
|
||||||
|
This is a simple crate built around [jni-rs](https://github.com/jni-rs/jni-rs) to automatically generate JNI-compatible extern functions.
|
||||||
|
|
||||||
this is a simple crate built around [jni-rs](https://github.com/jni-rs/jni-rs) to automatically generate JNI-compatible extern functions
|
It also wraps functions returning `Result<>`, making short-circuiting easy.
|
||||||
|
|
||||||
it also wraps functions returning `Result<>`, making short-circuiting easy
|
## Usage
|
||||||
|
Just specify package and class on your function, and done!
|
||||||
## usage
|
|
||||||
just specify package and class on your function, and done!
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[jni_toolbox::jni(package = "your.package.path", class = "ContainerClass")]
|
#[jni_toolbox::jni(package = "your.package.path", class = "ContainerClass")]
|
||||||
|
@ -18,14 +17,13 @@ fn your_function_name(arg: String) -> Result<Vec<String>, String> {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### conversions
|
### Conversions
|
||||||
every type that must go into/from Java must implement `IntoJava` or `FromJava` (methods will receive a `&mut JNIEnv` and can return errors).
|
Every type that is meant to be sent to Java must implement `IntoJavaObject` (or, unlikely, `IntoJavaPrimitive`); every type that is meant to be
|
||||||
most primitives already have them implemented. conversions are automatic and the wrapper function will invoke IntoJava/FromJava for every type,
|
received from Java must implement `FromJava`. Most primitives and a few common types should already be implemented.
|
||||||
passing an environment reference.
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl<'j> IntoJava for MyClass {
|
impl<'j> IntoJavaObject for MyClass {
|
||||||
type T = jni::sys::jobject;
|
type T = jni::objects::JObject<'j>
|
||||||
fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result<Self::T, jni::errors::Error> {
|
fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result<Self::T, jni::errors::Error> {
|
||||||
let hello = env.new_string("world")?;
|
let hello = env.new_string("world")?;
|
||||||
// TODO!!
|
// TODO!!
|
||||||
|
@ -33,15 +31,16 @@ impl<'j> IntoJava for MyClass {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### pointers
|
### Pointers
|
||||||
to return pointer type values, add the `ptr` attribute
|
To return pointer type values, add the `ptr` attribute.
|
||||||
|
|
||||||
note that, while possible to pass raw pointers to the JVM, it is not safe by default and must be done with extreme care.
|
Note that, while it is possible to pass raw pointers to the JVM, it is not safe by default and must be done with extreme care.
|
||||||
|
|
||||||
### exceptions
|
### Exceptions
|
||||||
Errors are thrown automatically when a `Result` is an error. For your errors to work, you must implement the `JniToolboxError` trait for your errors,
|
Errors are thrown automatically when a `Result` is an error. For your errors to work, you must implement the `JniToolboxError` trait for your errors,
|
||||||
(which just returns the path to your Java error class) and then make a Java error wrapper which can be constructed with a single string argument.
|
(which just returns the path to your Java error class) and then make a Java error wrapper which can be constructed with a single string argument.
|
||||||
functions returning `Result`s will automatically have their return value unwrapped and, if is an err, throw an exception and return early.
|
|
||||||
|
Functions returning `Result`s will automatically have their return value unwrapped and, if is an err, throw an exception and return early.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl JniToolboxError for MyError {
|
impl JniToolboxError for MyError {
|
||||||
|
@ -53,19 +52,18 @@ impl JniToolboxError for MyError {
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package my.package.some;
|
package my.package.some;
|
||||||
public class MyError {
|
public class MyError extends Throwable {
|
||||||
public MyError(String x) {
|
public MyError(String x) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
to throw simple exceptions, it's possible to use the `exception` attribute. just pass your exception's path (must be constructable with a single string argument!)
|
To throw simple exceptions, it's possible to use the `exception` attribute. Pass the exception's fully qualified name (must have a constructor
|
||||||
|
that takes in a single `String` argument).
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
The following function:
|
||||||
### examples
|
|
||||||
the following function:
|
|
||||||
```rust
|
```rust
|
||||||
#[jni(package = "mp.code", class = "Client", ptr)]
|
#[jni(package = "mp.code", class = "Client", ptr)]
|
||||||
fn connect(config: Config) -> Result<Client, ConnectionError> {
|
fn connect(config: Config) -> Result<Client, ConnectionError> {
|
||||||
|
@ -73,15 +71,11 @@ fn connect(config: Config) -> Result<Client, ConnectionError> {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
gets turned into these two functions:
|
generates a matching expanded function invoking it:
|
||||||
|
|
||||||
<details><summary>show macro expansion</summary>
|
<details><summary>Show macro expansion</summary>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn connect(config: Config) -> Result<Client, ConnectionError> {
|
|
||||||
tokio().block_on(Client::connect(config))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub extern "system" fn Java_mp_code_Client_connect<'local>(
|
pub extern "system" fn Java_mp_code_Client_connect<'local>(
|
||||||
|
@ -157,9 +151,10 @@ pub extern "system" fn Java_mp_code_Client_connect<'local>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
## status
|
## Status
|
||||||
this crate is rather early and intended mostly to maintain [`codemp`](https://github.com/hexedtech/codemp) java bindings, however it's also quite small and only runs at comptime, so should be rather safe to use
|
This crate is early and intended mostly to maintain [`codemp`](https://github.com/hexedtech/codemp)'s Java bindings, so things not used
|
||||||
|
there may be missing or slightly broken. However, the crate is also quite small and only runs at compile time, so trying it out in your
|
||||||
|
own project should not be a problem.
|
||||||
|
|
|
@ -3,7 +3,7 @@ mod wrapper;
|
||||||
mod args;
|
mod args;
|
||||||
mod ret;
|
mod ret;
|
||||||
|
|
||||||
/// wrap this function in in a JNI exported fn
|
/// Wrap this function in in a JNI exported fn.
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn jni(
|
pub fn jni(
|
||||||
attrs: proc_macro::TokenStream,
|
attrs: proc_macro::TokenStream,
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -1,7 +1,9 @@
|
||||||
pub use jni_toolbox_macro::jni;
|
pub use jni_toolbox_macro::jni;
|
||||||
use jni::objects::{JObject, JObjectArray, JString};
|
use jni::objects::{JObject, JObjectArray, JString};
|
||||||
|
|
||||||
|
/// An error that is meant to be used with jni-toolbox.
|
||||||
pub trait JniToolboxError: std::error::Error {
|
pub trait JniToolboxError: std::error::Error {
|
||||||
|
/// The Java class for the matching exception.
|
||||||
fn jclass(&self) -> String;
|
fn jclass(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +19,17 @@ impl JniToolboxError for jni::errors::JniError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used in the generated code to have proper type bindings. You probably didn't want
|
||||||
|
/// to call this directly.
|
||||||
pub fn from_java_static<'j, T: FromJava<'j>>(env: &mut jni::JNIEnv<'j>, val: T::T) -> Result<T, jni::errors::Error> {
|
pub fn from_java_static<'j, T: FromJava<'j>>(env: &mut jni::JNIEnv<'j>, val: T::T) -> Result<T, jni::errors::Error> {
|
||||||
T::from_java(env, val)
|
T::from_java(env, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specifies how a Java type should be converted before being fed to Rust.
|
||||||
pub trait FromJava<'j> : Sized {
|
pub trait FromJava<'j> : Sized {
|
||||||
|
/// The JNI type representing the input.
|
||||||
type T : Sized;
|
type T : Sized;
|
||||||
|
/// Attempts to convert this Java object into its Rust counterpart.
|
||||||
fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::T) -> Result<Self, jni::errors::Error>;
|
fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::T) -> Result<Self, jni::errors::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +101,11 @@ impl<'j> FromJava<'j> for uuid::Uuid {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specifies how a Rust type should be converted into a Java primitive.
|
||||||
pub trait IntoJavaPrimitive<'j> {
|
pub trait IntoJavaPrimitive<'j> {
|
||||||
|
/// The JNI type representing the output.
|
||||||
type T;
|
type T;
|
||||||
|
/// Attempts to convert this Rust object into a Java primitive.
|
||||||
fn into_java(self, _: &mut jni::JNIEnv<'j>) -> Result<Self::T, jni::errors::Error>;
|
fn into_java(self, _: &mut jni::JNIEnv<'j>) -> Result<Self::T, jni::errors::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +140,12 @@ impl<'j> IntoJavaPrimitive<'j> for bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specifies how a Rust type should be converted into a Java object.
|
||||||
pub trait IntoJavaObject<'j> {
|
pub trait IntoJavaObject<'j> {
|
||||||
type T: std::convert::AsRef<JObject<'j>>;
|
type T: std::convert::AsRef<JObject<'j>>;
|
||||||
|
/// The Java class associated with this type.
|
||||||
const CLASS: &'static str;
|
const CLASS: &'static str;
|
||||||
|
/// Attempts to convert this Rust object into a Java object.
|
||||||
fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result<Self::T, jni::errors::Error>;
|
fn into_java(self, env: &mut jni::JNIEnv<'j>) -> Result<Self::T, jni::errors::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue