English | 中文
uniffi-bindgen-arkts generates HarmonyOS/ArkTS bindings for Rust crates that expose a UniFFI interface.
The generated package has two parts:
- An ArkTS package: public APIs, type declarations, and UniFFI serialization runtime.
- A generated OHOS N-API Rust adapter crate: the native layer that calls UniFFI FFI symbols.
ArkTS does not call UniFFI C ABI symbols directly. Your OHOS app imports the generated ArkTS package, and the generated native adapter is compiled into the lib<module>.so loaded by ArkTS.
Install the published command-line tool:
cargo install uniffi-bindgen-arkts --lockedCheck that the command is available:
uniffi-bindgen-arkts --helpAll examples below assume you are using the installed uniffi-bindgen-arkts command, not running this repository from source.
Your Rust crate should already be a normal UniFFI crate. For UDL-based crates, the Rust-side layout usually looks like this:
your-crate/
Cargo.toml
build.rs
src/
lib.rs
your_crate.udl
build.rs:
fn main() {
uniffi_build::generate_scaffolding("src/your_crate.udl").unwrap();
}Cargo.toml:
[lib]
crate-type = ["cdylib"]
[dependencies]
uniffi = "0.31.0"
[build-dependencies]
uniffi_build = "0.31.0"Build the UniFFI dynamic library for the target you want to package:
cargo build --releaseThe generator consumes the built libyour_crate.so, libyour_crate.dylib, or your_crate.dll. It does not consume .udl files directly and it does not depend on your Rust crate from the generated native adapter.
Run the installed generator:
uniffi-bindgen-arkts generate \
/path/to/target/release/libyour_crate.so \
--manifest-path /path/to/your-crate/Cargo.toml \
--out-dir /path/to/generated/your-crate \
--package-name @your-scope/your-crate \
--module-name your_crate \
--manual-loadWhat each required value means:
| Value | Meaning |
|---|---|
LIB_SOURCE |
Built UniFFI cdylib: .so, .dylib, or .dll. |
--manifest-path |
Your Rust crate manifest. It is used for UniFFI and ArkTS config lookup. |
--out-dir |
The generated Harmony package directory. |
--package-name |
The package name imported from ArkTS. |
--module-name |
The native module name. This controls lib<module>.so and generated file names. |
If the cdylib contains metadata for multiple UniFFI crates, select one component:
uniffi-bindgen-arkts generate \
/path/to/target/release/libyour_crate.so \
--manifest-path /path/to/your-crate/Cargo.toml \
--crate-name your_crate \
--out-dir /path/to/generated/your-crate \
--package-name @your-scope/your-crate \
--module-name your_crate \
--manual-loadThe generated directory looks like this:
your-crate/
oh-package.json5
index.ets
index.d.ts
src/
main/
ets/
your-crate.ets
your-crate.d.ts
runtime/
*.ets
module.json5
types/
libyour_crate/
Index.d.ts
oh-package.json5
native/
build.rs
Cargo.toml
src/lib.rs
Important files:
| Path | Purpose |
|---|---|
index.ets |
Re-exports the generated public ArkTS API. |
src/main/ets/<module>.ets |
The generated ArkTS API implementation. |
src/main/module.json5 |
Minimal HAR module descriptor for direct DevEco/Harmony module import. |
src/main/ets/runtime/*.ets |
UniFFI serialization, error, object, async, and callback helpers. |
types/lib<module>/Index.d.ts |
Type declarations for the native OHOS module. |
native/ |
Generated Rust N-API adapter crate. Compile this crate into the ArkTS-loaded lib<module>.so. |
libs/<abi>/ |
Staged input UniFFI cdylib when staging is enabled. |
Enter the generated native directory:
cd /path/to/generated/your-crate/native
cargo build --release --target aarch64-unknown-linux-ohosThe output is:
target/aarch64-unknown-linux-ohos/release/libyour_crate.so
This .so is the native module used by the generated ArkTS package. In a real OHOS project, your build system should compile this adapter and package the resulting .so into the HAP.
The adapter links to the input UniFFI cdylib. With the default staging behavior, the generator copies that input library into libs/<abi>/, and the generated native/build.rs links that package-local directory.
If you pass --no-stage-library, the generated package does not contain the input UniFFI cdylib. Your external build system must provide the library and set UNIFFI_ARKTS_LINK_SEARCH_DIR when compiling the generated native adapter.
One common layout is:
ohos-app/
entry/
vendor/
your-crate/
oh-package.json5
index.ets
src/main/ets/
types/
native/
Add the generated package to the app's oh-package.json5:
{
dependencies: {
"@your-scope/your-crate": "file:./vendor/your-crate",
},
}The generated package itself contains a native dependency like this:
{
dependencies: {
"libyour_crate.so": "file:./types/libyour_crate",
},
}Make sure the compiled libyour_crate.so is packaged into the app for every target ABI you support.
With --manual-load:
import { uniffiLoad, uniffiUnload, someFunction } from "@your-scope/your-crate";
uniffiLoad();
const value = someFunction("input");
uniffiUnload();Without --manual-load, import and call the generated APIs directly:
import { someFunction } from "@your-scope/your-crate";
const value = someFunction("input");Async Rust functions are exposed as Promise<T>:
const value = await delayedEcho("input");You can put defaults in the Rust crate's uniffi.toml:
[bindings.arkts]
package_name = "@your-scope/your-crate"
module_name = "your_crate"
manual_load = true
stage_library = true
abi = "arm64-v8a"Supported keys:
package_namemodule_namemanual_loadstage_libraryabirenameexternal_packages
CLI flags override uniffi.toml.
External UniFFI types require package mappings:
[bindings.arkts.external_packages."geometry-fixture"]
package_name = "@fixture/geometry"
dependency = "file:../geometry"The generated ArkTS code imports external converters from package_name, and the generated oh-package.json5 includes dependency when it is set.
uniffi-bindgen-arkts generate [OPTIONS] --out-dir <OUT_DIR> <LIB_SOURCE>
Options:
LIB_SOURCE: built UniFFI cdylib:.so,.dylib, or.dll.--manifest-path <Cargo.toml>: Rust crate manifest used for UniFFI and ArkTS config lookup.--out-dir <OUT_DIR>: generated ArkTS package directory.--package-name <NAME>: generated Harmony package name.--module-name <NAME>: module name used for generated files and native module imports.--manual-load: exportuniffiLoad()anduniffiUnload().--no-stage-library: do not copy the input cdylib into the generated package. External builds must setUNIFFI_ARKTS_LINK_SEARCH_DIR.--abi <ABI>: ABI directory for staged libraries. Defaults toarm64-v8a.--crate-name <NAME>: select one component when the input contains multiple UniFFI components.
Covered by fixtures:
- Top-level synchronous functions.
- Async functions and object methods as
Promise<T>. - Async callbacks, including callbacks triggered from Rust async tasks.
- Records as ArkTS
interface. - Flat enums as
export enum. - Tagged enums as discriminated unions.
- Error enums as
Errorsubclasses. - Objects with constructors, methods, native handles, clone/free, and
destroy(). - UniFFI trait methods such as Debug, Display, Eq, Hash, and Ord exports.
- Callback interfaces with sync and async methods.
- External types through
bindings.arkts.external_packages. Option<T>asT | undefined.sequence<T>andset<T>asArray<T>.map<K, V>asMap<K, V>.bytesasUint8Array.timestampasDate.durationas milliseconds innumber.- 64-bit integers as
bigintin the public ArkTS API.
Type mapping:
| UniFFI | ArkTS |
|---|---|
u8/i8/u16/i16/u32/i32 |
number |
u64/i64 |
bigint |
f32/f64 |
number |
boolean |
boolean |
string |
string |
bytes |
Uint8Array |
timestamp |
Date |
duration |
number |
record |
interface |
flat enum |
export enum |
tagged enum |
discriminated union |
error enum |
Error subclass |
object |
native-handle-backed class |
Generation rejects these UniFFI surfaces:
- Async constructors.
- Custom types.
- Record constructors.
- Record methods.
- Record UniFFI trait methods.
- Enum constructors.
- Enum methods.
- Enum UniFFI trait methods.
This section is only for working on the uniffi-bindgen-arkts repository itself. Users of the published package should use the installed CLI shown above.
Install development tools:
pnpm install
pnpm run prepareFormat staged files before commit:
pnpm run formatRun local checks:
cargo test
cargo check --workspaceRun the OHOS smoke test with a real project:
OHOS_SMOKE_PROJECT_DIR=/path/to/ohos/project REQUIRE_OHOS_SMOKE=1 \
bash scripts/ci/run_ohos_smoke.shSet HDC_TARGET when the script should install the HAP and check hilog for PASS fixtures.