有没有一种简单的方法从Rust中调用Java函数?

3

我理解通过jni构架从Rust中调用Java,需要一些模板代码,大致如下:

je.call_method(self.rimuru, "shell2Pixels", "(II[B)V", &[
    JValue::from(width),
    JValue::from(height),
    JValue::from(rgbs.as_obj()),
])?;

我想可以使用宏来改进这个功能,类似于以下代码: java_call_method!(self.rimuru, "shell2Pixels", (), width, height, rgbs)?; 该宏将负责从各种参数的类型构建签名字符串(II[B)V
类似的功能已经存在了吗?我不确定是否可以使用普通宏而不是过程宏来实现。

字符串(II[B)V表示你正在传递的参数类型,还是函数期望的类型?如果是后者,构建该字符串的宏将非常不安全。 - mcarton
(II[B)V 表示传递给宏的类型。如果它们与 Java 类中可用的不匹配,那么我希望 Java 抛出 NoSuchMethodException 异常。 - Mutant Bob
这种方法可能适用于原始类型,但对于引用类型(对象和数组)很快就变得不可行。你可以在编译时解释给定的类型签名,并使用它来检查参数的类型。 - Botje
支持对象和数组可能有些棘手,我想多层次的支持是可能的(其中一种只需传递一个 jobject,而其他更高级别的层次则需要模板化的包装类)。但在版本1中,我不会处理这个问题。 - Mutant Bob
1个回答

1

在彷徨不知所措后,我创建了https://github.com/mutantbob/rust_jni_boilerplate,其中包含一小组生成样板文件的过程宏。

(截至2020年8月) 使用方式如下:

struct Widget<'a> {
    jni_env: &'a AttachGuard<'a>,
    java_this: AutoLocal<'a,'a>,
}

impl<'a> JavaConstructible<'a> for Widget<'a>
{
    fn wrap_jobject(jni_env:&'a AttachGuard<'a>, java_this: AutoLocal<'a,'a>) -> Widget<'a>
    {
        Widget {
            jni_env,
            java_this,
        }
    }
}

impl<'a> Widget<'a> {

    // define a rust function named new
    jni_constructor! { com.purplefrog.rust_callables.Widget () }
    jni_constructor! { new_one=com.purplefrog.rust_callables.Widget (&str) }

    jni_instance_method! { count () -> i32 }
    jni_instance_method! { sumLen () -> i32 }

    jni_instance_method! { add(&str) }

    jni_instance_method! { echo_str=echo(&str)->String }
    jni_instance_method! { echo_char=echo(char)->char }
    jni_instance_method! { echo_byte=echo(i8)->i8 }
    jni_instance_method! { echo_short=echo(i16)->i16 }
    jni_instance_method! { echo_int=echo(i32)->i32 }
    jni_instance_method! { echo_long=echo(i64)->i64 }

    jni_instance_method! { to_strings = toStrings() ->Vec<String> }
}

它的类型支持可能存在严重漏洞。在开发过程中,其架构已经发生了巨大的变化。我甚至不确定我是否正确地使用了过程宏 API。它基于的 jni crate 很难被认为是安全的(当你从 rust 调用 java 时很容易泄露内存)。但是我已经成功地使它适用于我的有限使用情况。

我希望它能激励其他人做得更好。也许它将作为编写过程宏的示例很有用,直到有人撰写一篇合适的文章(谷歌搜索并没有给我任何好的文章)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接