OHOS_NAPI_RS
Introduction
ohos_napi_rs(forked from napi-rs) is a framework used to implement communication between ArkTS and Rust. Provides users with the ability to call ArkTS and Rust to each other.
Figure 1 The position of ohos_napi_rs in OpenHarmony

In general, OpenHarmony application development uses ArkTS/JS language, but in some scenarios where performance and efficiency are required, such as games, physics simulations, etc., existing C/C++libraries need to be relied upon. ohos_napi_rs provides developers with the ability to interact between ArkTS and Rust modules. Including ArkTS and Rust data type conversion, as well as the ability to call functions to each other.
ArkTS:OpenHarmony application development language;ArkTS Native Module(Rust):Native module developed using Rust;ArkTS Native Module(C++):Native module developed using C++;ohos_napi_rs:Provide ArkTS and Rust interaction capabilities;Node-API:Napi interface, enabling interaction between ArkTS and C/C++;
Figure 2 The internal structure of ohos_napi_rs

ohos_napi_rs is mainly divided into three modules internally:
Rust sys:Using Rust CFFI to encapsulate the underlying Napi interface;Rust napi:Implement mutual conversion between Rust data types and ArkTS data types; Provide the logic for registering Rust functions into ArkTS;Rust macro:Provide process macros for users, such as #[napi], to automatically complete ArkTS and Rust data type conversion, and Rust function registration functions;
Directory
ohos_napi_rs
├── crates
│ ├── backend
│ │ └── src # The underlying implementation logic of process macros
│ │ ├── codegen # Macros automatically generate type conversion and function registration code
│ │ └── typegen # Macros automatically generate ArkT function header file logic (d.ts)
│ ├── build
│ │ └── src # Build Script
│ ├── macro
│ │ └── src # Implementation of External Interface for Process Macros
│ │ ├── expand # Process macro external interface
│ │ └── parser # Process macro tokenStream parsing
│ ├── napi
│ │ └── src
│ │ ├── bindgen_runtime # Rust function registration and type conversion
│ │ │ └── js_values # Rust native data type and ArkTS type conversion logic implementation
│ │ └── js_values # Rust safe reference type and ArkTS type conversion logic implementation
│ │ └── string # Rust String types, such as latin1, utf16, utf8
│ └── sys
│ └── src # Rust CFFI encapsulates the underlying Napi interface
├── docs # User's guide
└── figures # Resources
Compile
Use Cargo
-
Environment preparation, install Rust and ohos sdk.
Rust needs to ensure version>=1.78.0 and install the toolchain corresponding to OpenHarmony.
rustup target add aarch64-unknown-linux-ohos rustup target add armv7-unknown-linux-ohos rustup target add x86_64-unknown-linux-ohosOhos sdk can be obtained from daily builds, which includes the native library and compilation toolchains.
-
Create a new Rust project, introduce 'ohos_napi_rs' in' Cargo. toml ', and set the Rust output library type to cdylib.
[dependencies] napi = {path = "ohos_napi_rs/crates/napi"} napi-derive = {path = "ohos_napi_rs/crates/macro"} [build-dependencies] napi-build = {path = "ohos_napi_rs/crates/build"} [lib] crate-type=["cdylib"] -
Add the Rust build script build.rs.
// build.rs fn main() { napi_build::setup(); } -
Develop Rust code.
use napi_derive::napi; #[napi] fn add(a: u32, b: u32) -> u32 { a + b } -
Set up the linker used for Rust build and create a. cargo/config. toml file in the project.
Refer to the official Rust documentation
[target.x86_64-unknown-linux-ohos] linker = "/path/to/x86_64-unknown-linux-ohos-clang.sh" [target.armv7-unknown-linux-ohos] linker = "/path/to/armv7-unknown-linux-ohos-clang.sh" [target.aarch64-unknown-linux-ohos] linker = "/path/to/aarch64-unknown-linux-ohos-clang.sh"Create the following shell script to encapsulate the compilation toolchain from ohos sdk:
x86_64-unknown-linux-ohos-clang.sh:
#!/bin/sh exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ -target x86_64-linux-ohos \ --sysroot=/path/to/ohos-sdk/linux/native/sysroot \ -Wl --no-undefined \ -D__MUSL__ \ "$@"armv7-unknown-linux-ohos:
#!/bin/sh exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ -target arm-linux-ohos \ --sysroot=/path/to/ohos-sdk/linux/native/sysroot \ -Wl --no-undefined \ -D__MUSL__ \ -march=armv7-a \ -mfloat-abi=softfp \ -mtune=generic-armv7-a \ -mthumb \ "$@"aarch64-unknown-linux-ohos-clang.sh:
#!/bin/sh exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ -target aarch64-linux-ohos \ --sysroot=/path/to/ohos-sdk/linux/native/sysroot \ -Wl --no-undefined \ -D__MUSL__ \ "$@"Compile using the cargo command:
cargo build --target x86_64-unknown-linux-ohos --release cargo build --target armv7-unknown-linux-ohos --release cargo build --target aarch64-unknown-linux-ohos --release -
Add the so generated by Rust compilation to the ArkTS project as a pre built library, and add it to the corresponding platform directory. If there is no folder, create a new one.
arktsProject/entry/libs/arm64-v8a arktsProject/entry/libs/armeabi-v7a arktsProject/entry/libs/x86_64Add header file declarations in the arkts project and call Rust functions.
index.d.ts
export declare function add(a: number, b: number): number;Index.ets
import rustNapi from 'libarkts_napi_sdv.so'; let res: number = rustNapi.add(2, 4); expect(res).assertEqual(6);
Acknowledgements
This library is adapted based on thenapi-rs repository to achieve interoperability between ArkTS and Rust. We also referred to the implementation design of ohos-rs and would like to express our gratitude to napi rs and ohos rs.