如何使用从 rust Vec 中提取的参数列表调用可变参数 C 函数?

How can I call a variadic C function with a list of arguments pulled from a rust Vec?

我正在尝试从 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 Documentation