Reputation: 3549
My understanding of invoking java from rust via the jni
crate involves a bit of boilerplate that looks like
je.call_method(self.rimuru, "shell2Pixels", "(II[B)V", &[
JValue::from(width),
JValue::from(height),
JValue::from(rgbs.as_obj()),
])?;
I am imagining that this could be improved using macros. Perhaps something like
java_call_method!(self.rimuru, "shell2Pixels", (), width, height, rgbs)?;
The macro would be responsible for building the signature string (II[B)V
from the types of the various arguments.
Does something like this already exist and I have not discovered it? I am not sure if it can be implemented using regular macros instead of procedural macros.
Upvotes: 3
Views: 555
Reputation: 3549
After a great deal of wallowing in confusion I have created https://github.com/mutantbob/rust_jni_boilerplate which has a small set of procedural macros that generate boilerplate.
(as of 2020-Aug) It is used like this:
struct Widget<'a> {
jni_env: &'a AttachGuard<'a>,
java_this: AutoLocal<'a,'a>,
}
impl<'a> JavaConstructible<'a> for Widget<'a>
{
fn wrap_jobject(jni_env:&'a AttachGuard<'a>, java_this: AutoLocal<'a,'a>) -> Widget<'a>
{
Widget {
jni_env,
java_this,
}
}
}
impl<'a> Widget<'a> {
// define a rust function named new
jni_constructor! { com.purplefrog.rust_callables.Widget () }
jni_constructor! { new_one=com.purplefrog.rust_callables.Widget (&str) }
jni_instance_method! { count () -> i32 }
jni_instance_method! { sumLen () -> i32 }
jni_instance_method! { add(&str) }
jni_instance_method! { echo_str=echo(&str)->String }
jni_instance_method! { echo_char=echo(char)->char }
jni_instance_method! { echo_byte=echo(i8)->i8 }
jni_instance_method! { echo_short=echo(i16)->i16 }
jni_instance_method! { echo_int=echo(i32)->i32 }
jni_instance_method! { echo_long=echo(i64)->i64 }
jni_instance_method! { to_strings = toStrings() ->Vec<String> }
}
There are probably gaping holes in its type support. Its architecture has mutated drastically during development. I'm not even sure I'm using the procedural macro API idiomatically. The jni
crate it is based on can hardly be considered safe (it is very easy to leak memory when you are calling java from rust). But I have managed to make it work for my limited use case.
I am hoping it serves as an inspiration for someone else to do better. Maybe it will be useful as an example of how to write procedural macros until someone writes a proper article (google search didn't exactly give me any good articles about it).
Upvotes: 1