1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use jni::errors::Error as JniError;
use jni::objects::{GlobalRef, JObject};
use jni::sys::{jobject, jsize};
use jni::JNIEnv;
use std::os::raw::c_void;
pub type JniResult<T> = Result<T, JniError>;
#[macro_export]
macro_rules! jni_unwrap {
($res:expr) => {{
let res: Result<_, JniError> = $res;
if let Err(JniError(ErrorKind::JavaException, _)) = res {
return;
} else {
res.unwrap()
}
}};
}
#[macro_export]
macro_rules! gen_ctx {
($env:ident, $cb:ident) => {
{
let ctx = $env.new_global_ref($cb).unwrap();
$env.delete_local_ref($cb).unwrap();
let ptr = *ctx.as_obj() as *mut c_void;
mem::forget(ctx);
ptr
}
};
($env:ident, $cb0:ident, $($cb_rest:ident),+ ) => {
{
let ctx = [
Some($env.new_global_ref($cb0).unwrap()),
$(
Some($env.new_global_ref($cb_rest).unwrap()),
)+
];
let ctx = Box::into_raw(Box::new(ctx)) as *mut c_void;
$env.delete_local_ref($cb0).unwrap();
$(
$env.delete_local_ref($cb_rest).unwrap();
)+
ctx
}
}
}
#[macro_export]
macro_rules! gen_primitive_type_converter {
($native_type:ty, $java_type:ty) => {
impl FromJava<$java_type> for $native_type {
fn from_java(_env: &JNIEnv, input: $java_type) -> JniResult<Self> {
Ok(input as Self)
}
}
impl<'a> ToJava<'a, $java_type> for $native_type {
fn to_java(&self, _env: &JNIEnv) -> JniResult<$java_type> {
Ok(*self as $java_type)
}
}
};
}
#[macro_export]
macro_rules! gen_object_array_converter {
($native_type:ident, $java_ty_name:expr) => {
impl<'a, 'b> ToJava<'a, JObject<'a>> for &'b [$native_type] {
fn to_java(&self, env: &'a JNIEnv) -> JniResult<JObject<'a>> {
object_array_to_java($native_type::to_java, self, env, $java_ty_name)
}
}
};
}
#[macro_export]
macro_rules! gen_byte_array_converter {
($arr_type:ty, $size:expr) => {
impl<'a> FromJava<JObject<'a>> for [$arr_type; $size] {
fn from_java(env: &JNIEnv, input: JObject) -> JniResult<Self> {
let input = input.into_inner() as jbyteArray;
let mut output = [0; $size];
let len = env.get_array_length(input)? as usize;
env.get_byte_array_region(input, 0, &mut output[0..cmp::min(len, $size)])?;
Ok(unsafe { mem::transmute(output) })
}
}
impl<'a> ToJava<'a, JObject<'a>> for [$arr_type; $size] {
fn to_java(&self, env: &'a JNIEnv) -> JniResult<JObject<'a>> {
let output = env.new_byte_array(self.len() as jsize)?;
env.set_byte_array_region(output, 0, unsafe {
slice::from_raw_parts(self.as_ptr() as *const i8, self.len())
})?;
Ok(JObject::from(output as jobject))
}
}
};
}
pub fn object_array_to_java<
'a,
T,
F: Fn(&T, &'a JNIEnv) -> JniResult<U>,
U: Into<JObject<'a>> + 'a,
>(
transform_fn: F,
list: &[T],
env: &'a JNIEnv,
class: &str,
) -> JniResult<JObject<'a>> {
let output = env.new_object_array(list.len() as jsize, class, JObject::null())?;
for (idx, entry) in list.iter().enumerate() {
let jentry = transform_fn(entry, env)?.into();
env.set_object_array_element(output, idx as i32, jentry)?;
}
Ok(JObject::from(output))
}
pub unsafe fn convert_cb_from_java(env: &JNIEnv, ctx: *mut c_void) -> GlobalRef {
GlobalRef::from_raw(unwrap!(env.get_java_vm()), ctx as jobject)
}