Compare commits

..

11 Commits

3 changed files with 174 additions and 52 deletions

View File

@@ -1,24 +1,7 @@
Rust build Rust bindings to the JNI Demo.
Run
```shell ```shell
cd mylib > make java_run
cargo build
```
Java build
```shell
cd java_src
javac me/ehlxr/HelloWorld.java
```
Java run
```shell
cd java_src
# Linux: export LD_LIBRARY_PATH=../mylib/target/debug/
# export JAVA_LIBRARY_PATH=../mylib/target/debug/
java -Djava.library.path=../mylib/target/debug/ me.ehlxr.HelloWorld
``` ```

View File

@@ -2,6 +2,7 @@ package me.ehlxr;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
class HelloWorld { class HelloWorld {
static { static {
@@ -13,7 +14,7 @@ class HelloWorld {
public Long no; public Long no;
private String name; private String name;
public int age; public int age;
public List<String> ls; public List<String> list;
public Map<String, Long> map; public Map<String, Long> map;
private static native String hello(String input); private static native String hello(String input);
@@ -30,7 +31,7 @@ class HelloWorld {
private static native void asyncComputation(HelloWorld callback); private static native void asyncComputation(HelloWorld callback);
private static native String getFiled(HelloWorld param); private static native List<Map<String, Object>> getField(HelloWorld param);
public static void main(String[] args) { public static void main(String[] args) {
String output = HelloWorld.hello("Java"); String output = HelloWorld.hello("Java");
@@ -56,12 +57,19 @@ class HelloWorld {
ls.add("ls1"); ls.add("ls1");
ls.add("ls2"); ls.add("ls2");
ls.add("ls3"); ls.add("ls3");
Map<String, Long> map = new HashMap<>();
map.put("k1", 1L);
map.put("k2", 2L);
map.put("k3", 3L);
HelloWorld hw = new HelloWorld(); HelloWorld hw = new HelloWorld();
hw.setName("Jack"); hw.setName("Jack");
hw.no = 123434555L; hw.no = 123434555L;
hw.age = 30; hw.age = 30;
hw.ls = ls; hw.list = ls;
System.out.println(HelloWorld.getFiled(hw)); hw.map = map;
System.out.println("get return: " + HelloWorld.getField(hw));
} }
public String getName() { public String getName() {

View File

@@ -1,17 +1,53 @@
use jni::objects::{GlobalRef, JClass, JList, JObject, JString, JValue}; use jni::{
use jni::sys::{jbyteArray, jint, jlong, jstring}; errors::Result,
use jni::JNIEnv; objects::{GlobalRef, JClass, JList, JMap, JObject, JString, JValue},
sys::{jbyteArray, jint, jlong, jobject, jstring},
JNIEnv,
};
use std::{sync::mpsc, thread, time::Duration}; use std::{sync::mpsc, thread, time::Duration};
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_me_ehlxr_HelloWorld_getFiled( pub extern "system" fn Java_me_ehlxr_HelloWorld_getField(
env: JNIEnv, env: JNIEnv,
_class: JClass, _class: JClass,
input: JObject, input: JObject,
) -> jstring { ) -> jobject {
// Map field operate
let jmap = env
.get_map(
env.get_field(input, "map", "Ljava/util/Map;")
.unwrap()
.l()
.unwrap(),
)
.unwrap();
let v1 = jmap
.get(JObject::from(env.new_string("k1").unwrap()))
.unwrap()
.unwrap();
println!("get map key k1, value: {}", long_value(env, v1));
if let Ok(_) = jmap.put(
JObject::from(env.new_string("k9").unwrap()),
long_to_jobj(env, 9 as i64),
) {
println!("put key ok");
};
jmap.iter().unwrap().into_iter().for_each(|jmap_iter| {
let key: JString = jmap_iter.0.into();
let value = jmap_iter.1;
println!(
"iter map key: {}, value: {}",
String::from(env.get_string(key).unwrap()),
long_value(env, value)
);
});
// List field operate
let jlist = env let jlist = env
.get_list( .get_list(
env.get_field(input, "ls", "Ljava/util/List;") env.get_field(input, "list", "Ljava/util/List;")
.unwrap() .unwrap()
.l() .l()
.unwrap(), .unwrap(),
@@ -20,14 +56,16 @@ pub extern "system" fn Java_me_ehlxr_HelloWorld_getFiled(
jlist.iter().unwrap().into_iter().for_each(|jobj| { jlist.iter().unwrap().into_iter().for_each(|jobj| {
let jstr: JString = jobj.into(); let jstr: JString = jobj.into();
println!( println!(
"get list filed: {}", "get list field: {}",
String::from(env.get_string(jstr).unwrap()) String::from(env.get_string(jstr).unwrap())
); );
}); });
// int field operate
let age = env.get_field(input, "age", "I").unwrap().i().unwrap(); let age = env.get_field(input, "age", "I").unwrap().i().unwrap();
println!("get age field: {}", age); println!("get age field: {}", age);
// String field operate
let name: JString = env let name: JString = env
.get_field(input, "name", "Ljava/lang/String;") .get_field(input, "name", "Ljava/lang/String;")
.unwrap() .unwrap()
@@ -39,24 +77,17 @@ pub extern "system" fn Java_me_ehlxr_HelloWorld_getFiled(
String::from(env.get_string(name).unwrap()) String::from(env.get_string(name).unwrap())
); );
// let no = env.get_field(input, "no", "J").unwrap().j().unwrap(); // Long field operate
// println!("get no field: {}", no); let no = long_value(
env,
let no = env env.get_field(input, "no", "Ljava/lang/Long;")
.call_method( .unwrap()
env.get_field(input, "no", "Ljava/lang/Long;") .l()
.unwrap() .unwrap(),
.l() );
.unwrap(),
"longValue",
"()J",
&[],
)
.unwrap()
.j()
.unwrap();
println!("get no field: {}", no); println!("get no field: {}", no);
// call method operate
let out_str = if let JValue::Object(result) = env let out_str = if let JValue::Object(result) = env
.call_method(input, "getName", "()Ljava/lang/String;", &[]) .call_method(input, "getName", "()Ljava/lang/String;", &[])
.unwrap() .unwrap()
@@ -67,11 +98,76 @@ pub extern "system" fn Java_me_ehlxr_HelloWorld_getFiled(
} else { } else {
"".to_string() "".to_string()
}; };
println!("Hello {}! from Rust..", out_str);
let output = env // new ArrayList operate
.new_string(format!("Hello {}! from Rust..", out_str)) let list = unwrap(
.expect("Couldn't create java string!"); &env,
output.into_inner() JList::from_env(
&env,
unwrap(&env, env.new_object("java/util/ArrayList", "()V", &[])),
),
);
// new LinkedHashMap operate
let map = unwrap(
&env,
JMap::from_env(
&env,
unwrap(&env, env.new_object("java/util/LinkedHashMap", "()V", &[])),
),
);
// Map put key value operate
unwrap(
&env,
map.put(
JObject::from(env.new_string("no").unwrap()),
long_to_jobj(env, no),
),
);
unwrap(
&env,
map.put(
JObject::from(env.new_string("age").unwrap()),
long_to_jobj(env, age as i64),
),
);
unwrap(
&env,
map.put(
JObject::from(env.new_string("name").unwrap()),
JObject::from(name),
),
);
unwrap(
&env,
map.put(
JObject::from(env.new_string("list").unwrap()),
JObject::from(jlist),
),
);
unwrap(
&env,
map.put(
JObject::from(env.new_string("map").unwrap()),
JObject::from(jmap),
),
);
let jmap2 = map.clone();
// List add element operate
unwrap(&env, list.add(JObject::from(map)));
unwrap(&env, list.add(jmap2));
println!("list size {}", list.size().unwrap());
list.into_inner()
// let output = env
// .new_string(format!("Hello {}! from Rust..", out_str))
// .expect("Couldn't create java string!");
// output.into_inner()
} }
#[no_mangle] #[no_mangle]
@@ -203,6 +299,41 @@ pub extern "system" fn Java_me_ehlxr_HelloWorld_asyncComputation(
rx.recv().unwrap(); rx.recv().unwrap();
} }
fn long_value(env: JNIEnv, jobj: JObject) -> i64 {
env.call_method(jobj, "longValue", "()J", &[])
.unwrap()
.j()
.unwrap()
}
fn long_to_jobj<'a>(env: JNIEnv<'a>, lv: i64) -> JObject<'a> {
env.call_static_method(
"Ljava/lang/Long;",
"valueOf",
"(J)Ljava/lang/Long;",
&[JValue::from(lv)],
)
.unwrap()
.l()
.unwrap()
}
pub fn print_exception(env: &JNIEnv) {
let exception_occurred = env.exception_check().unwrap_or_else(|e| panic!("{:?}", e));
if exception_occurred {
env.exception_describe()
.unwrap_or_else(|e| panic!("{:?}", e));
}
}
#[allow(dead_code)]
pub fn unwrap<T>(env: &JNIEnv, res: Result<T>) -> T {
res.unwrap_or_else(|e| {
print_exception(&env);
panic!("{:#?}", e);
})
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]