我正在尝试从 rust 调用 JNI 函数CallStaticVoidMethod
。 jni-sys 包装器将其声明为
pub CallStaticVoidMethod:
Option<unsafe extern "C" fn(env: *mut JNIEnv, cls: jclass, methodID: jmethodID, ...)>,
我想用更安全的方式包装这个调用,所以我在我的包装对象上创建了这个方法:
pub fn call_static_void_method(&mut self, cls: jclass, method: jmethod, args: & Vec<jobject>)
{
let csvm;
unsafe {
csvm = (**self.env_ptr).CallStaticVoidMethod.expect("no implementation of CallStaticVoidMethod");
}
unsafe {
return csvm(self.env_ptr, cls, method, /*what here?*/);
}
}
如何转换args:Vec<jobject>
以便为CallStaticVoidMethod
JNI 函数提供最终参数?
你可以用正常的方式从 rust 调用可变参数 C 函数,但是使用仅在运行时知道的参数列表调用它们是另一回事。据我了解,这在 C 语言中甚至是不可能的(至少不是以符合标准的方式)。
不过,幸运的是,看起来您不需要这样做。JNI 提供了一种替代方法,CallStaticVoidMethodA
,定义为:
NativeType CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args);
其中args
指向包含参数的数组,形式为jvalue
。
你收到一个Vec<jobject>
;jvalue
是各种值的并集,所以你需要将你的Vec<jobject>
转换为一个jvalue
数组。 或者,如果您的函数可以接受Vec<jvalue>
,因为您将能够调用接受各种参数类型的方法 - 在这种情况下,您可以像这样传递args.as_ptr()
:
pub fn call_static_void_method(&mut self, cls: jclass, method: jmethod, args: & Vec<jvalue>)
{
let csvm;
unsafe {
csvm = (**self.env_ptr).CallStaticVoidMethodA.expect("no implementation of CallStaticVoidMethodA");
}
unsafe {
return csvm(self.env_ptr, cls, method, args.as_ptr());
}
}
对于用于调用方法的所有 JNI 函数,此主题都有变体。
另请参阅:JNI 文档