mirror of
https://github.com/hexedtech/jni-toolbox.git
synced 2024-11-22 07:24:53 +01:00
feat: impl JniToolboxError, allow returning ptr
This commit is contained in:
parent
f37c1ed7ae
commit
19ebaddd6d
3 changed files with 28 additions and 7 deletions
|
@ -14,3 +14,4 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
jni-toolbox-macro = "0.1.1"
|
jni-toolbox-macro = "0.1.1"
|
||||||
|
jni = "0.21"
|
||||||
|
|
|
@ -30,6 +30,7 @@ fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Result<TokenS
|
||||||
let mut package = None;
|
let mut package = None;
|
||||||
let mut clazz = None;
|
let mut clazz = None;
|
||||||
let mut exception = None;
|
let mut exception = None;
|
||||||
|
let mut return_pointer = false;
|
||||||
|
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
match what_next {
|
match what_next {
|
||||||
|
@ -39,6 +40,7 @@ fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Result<TokenS
|
||||||
"package" => what_next = WhatNext::Package,
|
"package" => what_next = WhatNext::Package,
|
||||||
"class" => what_next = WhatNext::Class,
|
"class" => what_next = WhatNext::Class,
|
||||||
"exception" => what_next = WhatNext::Exception,
|
"exception" => what_next = WhatNext::Exception,
|
||||||
|
"ptr" => return_pointer = true,
|
||||||
_ => return Err(syn::Error::new(Span::call_site(), "unexpected attribute on macro: {attr}")),
|
_ => return Err(syn::Error::new(Span::call_site(), "unexpected attribute on macro: {attr}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +120,7 @@ fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Result<TokenS
|
||||||
};
|
};
|
||||||
incoming.append_all(quote::quote!( #ty , ));
|
incoming.append_all(quote::quote!( #ty , ));
|
||||||
let pat = unpack_pat(*ty.pat)?;
|
let pat = unpack_pat(*ty.pat)?;
|
||||||
forwarding.append_all(quote::quote!( #pat , ));
|
forwarding.append_all(pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = fn_item.sig.ident.to_string();
|
let name = fn_item.sig.ident.to_string();
|
||||||
|
@ -130,17 +132,24 @@ fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Result<TokenS
|
||||||
return Err(syn::Error::new(Span::call_site(), "missing JNIEnv argument"));
|
return Err(syn::Error::new(Span::call_site(), "missing JNIEnv argument"));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let return_expr = if return_pointer {
|
||||||
|
quote::quote!( std::ptr::null_mut() )
|
||||||
|
} else {
|
||||||
|
quote::quote!( 0 )
|
||||||
|
};
|
||||||
|
|
||||||
let wrapped = if could_error {
|
let wrapped = if could_error {
|
||||||
if let Some(exception) = exception {
|
if let Some(exception) = exception {
|
||||||
// V----------------------------------V
|
// V----------------------------------V
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#[allow(unused_mut)]
|
||||||
pub extern "system" fn #fn_name<'local>(#incoming) #ret_type {
|
pub extern "system" fn #fn_name<'local>(#incoming) #ret_type {
|
||||||
use jni_toolbox::JniToolboxError;
|
use jni_toolbox::JniToolboxError;
|
||||||
match #fn_name_inner(#forwarding) {
|
match #fn_name_inner(#forwarding) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
Err(e) => match #env_ident.throw_new(#exception, format!("{e:?}")) {
|
Err(e) => match #env_ident.throw_new(#exception, format!("{e:?}")) {
|
||||||
Ok(_) => return 0,
|
Ok(_) => return #return_expr,
|
||||||
Err(e) => panic!("error throwing java exception: {e}"),
|
Err(e) => panic!("error throwing java exception: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,18 +160,22 @@ fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Result<TokenS
|
||||||
// V----------------------------------V
|
// V----------------------------------V
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#[allow(unused_mut)]
|
||||||
pub extern "system" fn #fn_name<'local>(#incoming) #ret_type {
|
pub extern "system" fn #fn_name<'local>(#incoming) #ret_type {
|
||||||
use jni_toolbox::JniToolboxError;
|
use jni_toolbox::JniToolboxError;
|
||||||
|
// NOTE: this is SAFE! the cloned env reference lives less than the actual one, we just lack a
|
||||||
|
// way to get it back from the called function and thus resort to unsafe cloning
|
||||||
|
let mut env_copy = unsafe { #env_ident.unsafe_clone() };
|
||||||
match #fn_name_inner(#forwarding) {
|
match #fn_name_inner(#forwarding) {
|
||||||
Err(e) => match #env_ident.find_class(e.jclass()) {
|
Err(e) => match env_copy.find_class(e.jclass()) {
|
||||||
Err(e) => panic!("error throwing Java exception -- failed resolving error class: {e}"),
|
Err(e) => panic!("error throwing Java exception -- failed resolving error class: {e}"),
|
||||||
Ok(class) => match #env_ident.new_string(format!("{e:?}")) {
|
Ok(class) => match env_copy.new_string(format!("{e:?}")) {
|
||||||
Err(e) => panic!("error throwing Java exception -- failed creating error string: {e}"),
|
Err(e) => panic!("error throwing Java exception -- failed creating error string: {e}"),
|
||||||
Ok(msg) => match #env_ident.new_object(class, "(Ljava/lang/String;)V", &[jni::objects::JValueGen::Object(&msg)]) {
|
Ok(msg) => match env_copy.new_object(class, "(Ljava/lang/String;)V", &[jni::objects::JValueGen::Object(&msg)]) {
|
||||||
Err(e) => panic!("error throwing Java exception -- failed creating object: {e}"),
|
Err(e) => panic!("error throwing Java exception -- failed creating object: {e}"),
|
||||||
Ok(obj) => match #env_ident.throw(obj) {
|
Ok(obj) => match env_copy.throw(jni::objects::JThrowable::from(obj)) {
|
||||||
Err(e) => panic!("error throwing Java exception -- failed throwing: {e}"),
|
Err(e) => panic!("error throwing Java exception -- failed throwing: {e}"),
|
||||||
Ok(_) => return 0,
|
Ok(_) => return #return_expr,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -177,6 +190,7 @@ fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Result<TokenS
|
||||||
// V----------------------------------V
|
// V----------------------------------V
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#[allow(unused_mut)]
|
||||||
pub extern "system" fn #fn_name<'local>(#incoming) #ret_type {
|
pub extern "system" fn #fn_name<'local>(#incoming) #ret_type {
|
||||||
#fn_name_inner(#forwarding)
|
#fn_name_inner(#forwarding)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,3 +3,9 @@ pub use jni_toolbox_macro::jni;
|
||||||
pub trait JniToolboxError: std::error::Error {
|
pub trait JniToolboxError: std::error::Error {
|
||||||
fn jclass(&self) -> String;
|
fn jclass(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl JniToolboxError for jni::errors::Error {
|
||||||
|
fn jclass(&self) -> String {
|
||||||
|
"java/lang/RuntimeException".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue