我正在尝试创建一个实现 BiConsumer 并在被调用时调用函数指针的类。
我对此有以下部分:
实例化实现 BiConsumer 的类的 Rust 代码:
// 'mc is defined by the struct that holds this function
pub fn from_rust_fn(
env: &JNIEnv<'mc>,
f: &'static dyn Fn(jni::objects::JObject, jni::objects::JObject),
) -> Result<Self, Box<dyn Error>> {
// Create the closure.
let closure: &'static _ =
Box::leak(Box::new(move |a: *mut _jobject, b: *mut _jobject| unsafe {
f(
jni::objects::JObject::from_raw(a),
jni::objects::JObject::from_raw(b),
);
}));
let callback = Closure2::new(closure);
let &code = callback.code_ptr();
let ptr: unsafe extern "C" fn(*const jobject) = unsafe { std::mem::transmute(code) };
std::mem::forget(callback);
// Create the java object.
let obj = env.new_object(
"net/ioixd/blackbox/BiConsumerLink",
"(J)V",
&[(ptr as i64).into()],
);
let obj = env.translate_error_no_gen(obj)?;
Self::from_raw(env, obj)
}
实现BiConsumer的类的Java代码:
import java.util.function.BiConsumer;
public class BiConsumerLink implements BiConsumer {
long address;
BiConsumerLink(long address) {
this.address = address;
}
public native void acceptNative(Object t, Object u);
public void accept(Object t, Object u) {
System.out.println((Object) t + "," + (Object) u);
acceptNative((Object) t, (Object) u);
}
}
以及链接到此类的另一段本机 Rust 代码:
type BiConsumer = unsafe extern "system" fn(t: JObject, u: JObject);
pub extern "system" fn Java_net_ioixd_blackbox_BiConsumerLink_acceptNative<'a>(
mut env: JNIEnv<'a>,
this: JObject,
obj1: JObject,
obj2: JObject,
) {
|| -> Result<(), Box<dyn Error>> {
let address = env.get_field(this, "address", "long")?.i()? as u64;
println!("{:#x}", address);
unsafe {
let func: BiConsumer = std::mem::transmute(address);
func(obj1, obj2);
}
Ok(())
}()
.unwrap();
}
当从 JNI 调用 BiConsumer 的“本机”方法时,它会抛出一个仅包含函数签名的错误,而不会尝试执行 Rust 代码:
void net.ioixd.blackbox.BiConsumerLink.acceptNative(java.lang.Object, java.lang.Object)
通常当 jni-rs 抛出此错误时,它表明我得到的函数签名错误。但在这种情况下,我已经检查了三次,这就是我应该得到的。我留下的假设是,这是我尝试通过覆盖方法执行此操作的结果。
我忘了在函数上方添加
[#no_mangle]
。