Skip to content

Repository files navigation

uniffi-bindgen-arkts

English | 中文

uniffi-bindgen-arkts generates HarmonyOS/ArkTS bindings for Rust crates that expose a UniFFI interface.

The generated package has two parts:

  1. An ArkTS package: public APIs, type declarations, and UniFFI serialization runtime.
  2. 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.

Integration

1. Install the Published CLI

Install the published command-line tool:

cargo install uniffi-bindgen-arkts --locked

Check that the command is available:

uniffi-bindgen-arkts --help

All examples below assume you are using the installed uniffi-bindgen-arkts command, not running this repository from source.

2. Build Your UniFFI cdylib

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 --release

The 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.

3. Generate the ArkTS Package

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-load

What 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-load

4. Check the Generated Output

The 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.

5. Compile the Native Adapter

Enter the generated native directory:

cd /path/to/generated/your-crate/native
cargo build --release --target aarch64-unknown-linux-ohos

The 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.

6. Add the Package to an OHOS App

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.

7. Use It from ArkTS

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");

Configuration

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_name
  • module_name
  • manual_load
  • stage_library
  • abi
  • rename
  • external_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.

CLI Reference

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: export uniffiLoad() and uniffiUnload().
  • --no-stage-library: do not copy the input cdylib into the generated package. External builds must set UNIFFI_ARKTS_LINK_SEARCH_DIR.
  • --abi <ABI>: ABI directory for staged libraries. Defaults to arm64-v8a.
  • --crate-name <NAME>: select one component when the input contains multiple UniFFI components.

Supported UniFFI Surface

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 Error subclasses.
  • 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> as T | undefined.
  • sequence<T> and set<T> as Array<T>.
  • map<K, V> as Map<K, V>.
  • bytes as Uint8Array.
  • timestamp as Date.
  • duration as milliseconds in number.
  • 64-bit integers as bigint in 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

Not Supported Yet

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.

Development

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 prepare

Format staged files before commit:

pnpm run format

Run local checks:

cargo test
cargo check --workspace

Run 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.sh

Set HDC_TARGET when the script should install the HAP and check hilog for PASS fixtures.

Credits

LICENSE

MIT

About

Generate ArkTS bindings for UniFFI Rust libraries.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages