1 个不稳定版本
新功能 0.1.0 | 2024 年 8 月 15 日 |
---|
#63 在 FFI 中
每月 157 次下载
170KB
3.5K SLoC
uniffi-bindgen-java
为 Java 生成 UniFFI 绑定。
已经存在官方 Kotlin 绑定,任何 JVM 语言(包括 Java)都可以使用。Java 特定的绑定尽可能使用 Java 原生类型以获得更直观的接口,例如,Java 绑定使用 CompletableFutures
而不是 kotlinx.coroutines
。
我们强烈建议您尽可能使用 UniFFI 的 proc-macro 定义 而不是 UDL。
需求
- Java 20+:
javac
和jar
- 下载 Java Native Access JAR,并将其路径添加到您的
$CLASSPATH
环境变量中。
安装
MSRV 是 1.77.0
。
cargoinstall uniffi-bindgen-java --githttps://github.com/IronCoreLabs/uniffi-bindgen-java
用法
uniffi-bindgen-java --help
Java scaffolding and bindings generator for Rust
Usage:
Commands:
generate Generate Java bindings
scaffolding Generate Rust scaffolding code
print-repr Print a debug representation of the interface from a dynamic library
Options:
-h, --help Print help
-V, --version Print version
生成绑定
uniffi-bindgen-java generate --help
Generate Java bindings
Usage:
Arguments:
<SOURCE> Path to the UDL file, or cdylib if `library-mode` is specified
Options:
-o, --out-dir <OUT_DIR> Directory in which to write generated files. Default is same folder as .udl file
-n, --no-format Do not try to format the generated bindings
-c, --config <CONFIG> Path to optional uniffi config file. This config is merged with the `uniffi.toml` config present in each crate, with its values taking precedence
--lib-file <LIB_FILE> Extract proc-macro metadata from a native lib (cdylib or staticlib) for this crate
--library Pass in a cdylib path rather than a UDL file
--crate <CRATE_NAME> When `--library` is passed, only generate bindings for one crate. When `--library` is not passed, use this as the crate name instead of attempting to locate and parse Cargo.toml
例如
> git clone https://github.com/mozilla/uniffi-rs.git
> cd uniffi-rs/examples/arithmetic-proc-macro
> cargo b --release
> uniffi-bindgen-java generate --out-dir ./generated-java --library ../../target/release/libarithmeticpm.so
> ll generated-java/uniffi/arithmeticpm/
total 216
-rw-r--r-- 1 user users 295 Jul 24 13:02 ArithmeticExceptionErrorHandler.java
-rw-r--r-- 1 user users 731 Jul 24 13:02 ArithmeticException.java
-rw-r--r-- 1 user users 3126 Jul 24 13:02 Arithmeticpm.java
-rw-r--r-- 1 user users 512 Jul 24 13:02 AutoCloseableHelper.java
-rw-r--r-- 1 user users 584 Jul 24 13:02 FfiConverterBoolean.java
...
> cat generated-java/uniffi/arithmeticpm/Arithmeticpm.java
package uniffi.arithmeticpm;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
public class Arithmeticpm {
public static Long add(Long a, Long b) throws ArithmeticException {
try {
...
生成框架
uniffi-bindgen-java scaffolding --help
Generate Rust scaffolding code
Usage:
Arguments:
<UDL_FILE> Path to the UDL file
Options:
-o, --out-dir <OUT_DIR> Directory in which to write generated files. Default is same folder as .udl file
-n, --no-format Do not try to format the generated bindings
打印调试表示
uniffi-bindgen-java print-repr --help
Print a debug representation of the interface from a dynamic library
Usage:
Arguments:
<PATH> Path to the library file (.so, .dll, .dylib, or .a)
集成绑定
生成后,您将得到一个包含 Java 文件的 --out-dir
目录。使用您选择的构建工具将这些文件打包成一个 .jar
文件,然后可以在任何具有可用 JNA
依赖项的 Java 项目中导入和使用结果。
Rust 库中的任何顶级函数都将作为以 crate 命名的一个类的静态方法。
配置
可以使用 uniffi.toml
配置文件配置生成的 Java。
配置名称 | 默认值 | 说明 |
---|---|---|
package_name |
uniffi |
Java包名 - 即在生成文件顶部package 语句中使用的值。 |
cdylib_name |
uniffi_{命名空间} |
包含FFI实现的编译好的Rust库的名称(使用generate --library 时不需要) |
generate_immutable_records |
false |
是否生成具有不可变字段的记录(使用record 代替class )。 |
custom_types |
一个映射,用于控制如何将自定义类型暴露给Java。请参阅UniFFI手册中自定义类型的部分 | |
external_packages |
一个映射,用于指定外部crates的包。键是Rust crate名称,值是用于引用该crate中类型的Java包。请参阅手册中外部类型的部分 | |
android |
false |
用于打开Android特定优化(警告:尚未经过良好测试) |
android_cleaner |
android |
使用android.system.SystemCleaner 代替java.lang.ref.Cleaner 。在两种情况下,回退都是JNA附带的内容。 |
示例
自定义类型
[bindings.java]
package_name = "customtypes"
[bindings.java.custom_types.Url]
# Name of the type in the Java code
type_name = "URL"
# Classes that need to be imported
imports = ["java.net.URI", "java.net.URL"]
# Functions to convert between strings and URLs
into_custom = "new URI({}).toURL()"
from_custom = "{}.toString()"
外部类型
[bindings.java.external_packages]
# This specifies that external types from the crate `rust-crate-name` will be referred by by the package `"java.package.name`.
rust-crate-name = "java.package.name"
注意
- CompletableFutures中的失败将导致它们
completeExceptionally
。导致失败的错误可以通过e.getCause()
进行检查。当在Java中实现异步Rust trait时,您需要使用completeExceptionally
而不是抛出异常。请参阅TestFixtureFutures.java
以查看具有错误示例的trait实现。 - Java中默认所有原始类型都是有符号的。Rust可以在被告知时正确地将Java中的有符号原始值解释为无符号。调用Uniffi函数的调用者需要在进行比较(
compareUnsigned
)或打印实际无符号值时注意这一点,以避免在这方面的陷阱。
不支持的功能
- Java不支持默认值,因此uniffi结构体、方法和函数默认值在Java代码中不存在。注意:可以通过生成构建器模式来支持结构体上的默认值,这是一个合理的案例。欢迎提交PR。
- 输出格式化目前不受支持,因为没有找到独立的命令行Java格式化程序。欢迎提交PR以启用该功能,基础设施已就绪。
测试
我们直接从Uniffi拉取固定的示例并使用生成的绑定运行Java测试。运行cargo t
以运行所有测试。
请注意,如果您需要为测试添加额外的toml条目,您可以将一个uniffi-extras.toml
放在测试的兄弟节点中,它将被读取,作为示例的基uniffi.toml
。请参阅CustomTypes以获取示例。在uniffi-extras.toml
中的设置适用于所有命名空间。
版本控制
uniffi-bindgen-java
与 uniffi-rs
的版本是分开管理的。我们遵循 Cargo SemVer 规则,因此当它们的最高非零主版本、次版本或补丁版本相同时,版本是兼容的。任何导致生成代码的消费者需要做出更改的生成器修改都被认为是破坏性的。
uniffi-bindgen-java
目前处于不稳定状态,由 IronCore Labs 开发,以支持 ironcore-alloy
所需的功能。当前主版本为 0,大多数更改可能会提升次版本号。
依赖项
~11MB
~190K SLoC