OHOS_NAPI_RS
简介
ohos_napi_rs(forked from napi-rs)是一个用于实现ArkTS和Rust通信的框架。为用户提供了ArkTS和Rust相互调用的能力。
图 1 ohos_napi_rs在 OpenHarmony 中的位置

一般情况下OpenHarmony应用开发使用ArkTS/JS语言,但部分场景由于性能、效率等要求,比如游戏、物理模拟等,需要依赖使用现有的C/C++库。
ohos_napi_rs为开发者提供ArkTS和Rust模块之间的交互能力。包括ArkTS和Rust数据类型转换、函数相互调用的能力。
ArkTS:OpenHarmony应用开发语言;ArkTS Native Module(Rust):使用Rust开发的native模块;ArkTS Native Module(C++):使用C++开发的native模块;ohos_napi_rs:提供ArkTS和Rust交互能力;Node-API:napi接口,实现ArkTS和C/C++交互能力;
图 2 ohos_napi_rs 内部架构图

ohos_napi_rs 内部主要分为三个模块:
Rust sys:使用Rust CFFI封装底层napi接口;Rust napi:实现Rust数据类型和ArkTS数据类型相互转换;提供Rust函数注册进ArkTS的逻辑;Rust macro:提供用户使用的过程宏,如#[napi],自动完成ArkTS和Rust数据类型转换、Rust函数注册功能;
目录
ohos_napi_rs
├── crates
│ ├── backend
│ │ └── src # 过程宏底层实现逻辑
│ │ ├── codegen # 过程宏自动生成类型转换、函数注册代码
│ │ └── typegen # 过程宏自动生成ArkT函数头文件逻辑(d.ts)
│ ├── build
│ │ └── src # 编译脚本
│ ├── macro
│ │ └── src # 过程宏对外接口实现
│ │ ├── expand # 过程宏对外接口
│ │ └── parser # 过程宏TokenStream解析
│ ├── napi
│ │ └── src
│ │ ├── bindgen_runtime # Rust函数注册、类型转换
│ │ │ └── js_values # Rust原生数据类型和ArkTS类型转换逻辑实现,如Rust(String)对应ArkTS(string)
│ │ └── js_values # Rust安全引用类型和ArkTS类型转换逻辑实现 ,如Rust(JsString)对应ArkTS(string)
│ │ └── string # Rust String类型,如latin1、utf16、utf8
│ └── sys
│ └── src # Rust CFFI封装底层napi接口
├── docs # 使用文档
└── figures # 架构图
编译构建
使用Cargo编译
-
环境准备,安装Rust和ohos-sdk。
Rust需要保证版本 >= 1.78.0,并且安装OpenHarmony对应的toolchain。
rustup target add aarch64-unknown-linux-ohos rustup target add armv7-unknown-linux-ohos rustup target add x86_64-unknown-linux-ohosohos-sdk可以从每日构建获取,ohos-sdk中包含native库和编译工具链。
-
新建Rust工程,在
Cargo.toml中引入ohos_napi_rs,设置Rust输出库类型为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"] -
添加Rust构建脚本build.rs。
// build.rs fn main() { napi_build::setup(); } -
开发Rust代码。
use napi_derive::napi; #[napi] fn add(a: u32, b: u32) -> u32 { a + b } -
设置Rust构建时使用的linker,在工程项目中新建.cargo/config.toml文件。
参考Rust官方文档
[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"创建以下shell脚本,从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__ \ "$@"使用cargo命令进行编译:
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 -
将Rust编译生成的so以预构建库的方式添加到ArkTS工程中,添加到以下对应平台的目录中,如果没有文件夹就新建。
arktsProject/entry/libs/arm64-v8a arktsProject/entry/libs/armeabi-v7a arktsProject/entry/libs/x86_64在arkts工程中添加头文件声明,并调用Rust函数。
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);
用户指南
详细内容请见用户指南
致谢
本库基于napi-rs仓库进行适配,完成ArkTS和Rust的互通功能。同时也参考了ohos-rs的实现设计,在此对napi-rs和ohos-rs表示感谢。