Arkts-NAPI-Rust-Demo
Arkts-NAPI-Rust-Demo copied to clipboard
使 Rust 开发华为鸿蒙 ArkTs N-API 原生模块的简单例程
【例程】Rust编程开发ArkTs NAPI原生模块
在该完整例程中,
- 既包含了
DevEco Studio的Empty Ability工程 - 也包括了
Cargo (Library) Package工程 - 更涵盖了ohos-node-bindgen的用例代码。
- 最后,
Cargo (Library) Package工程根目录下的build.rs与post_build.rs构建程序也能直接在其它同类Cargo Package工程内复用。
如何使普通的Empty Ability工程支持Rust原生模块开发
-
新建/打开
DevEco Studio工程。 -
修改模块级的
build-profile.json5文件。比如,entry/build-profile.json5文件。在buildOption节点下,添加如下配置数组"externalNativeOptions": { "abiFilters": [ "arm64-v8a", "armeabi-v7a", "x86_64" ] } -
在模块根目录下,创建如下三个目录
目录 CPU架构设备类型 模块根目录/libs/arm64-v8a 64位ARM CPU真机 模块根目录/libs/armeabi-v7a 32位ARM CPU真机 模块根目录/libs/x86_64 64位AMD / Intel CPU模拟器 -
在
模块根目录/src/main/目录下,创建rust文件夹。 -
在
模块根目录/src/main/rust文件夹内,使用cargo init --lib --name=<包名>命令初始Cargo Package工程-
【注意】交叉编译输出链接库的
ABI格式不是cdylib,而是dylib。在Cargo.toml中,该设置值有些反直觉[lib] crate-type = ["dylib"] -
DevEco Studio工程的新目录结构变为DevEco Studio 工程根目录 ├── entry — 模块根目录 │ ├── libs — 交叉编译输出的 *.so 文件都被复制到下面的子文件夹内 │ │ ├── arm64-v8a │ │ ├── armeabi-v7a │ │ └── x86_64 │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ ├── ets — 旧有的 ArkTs 源码目录 │ │ │ ├── rust — 新建的、专门盛放 Cargo (Lib) Package 工程的目录 │ │ │ │ ├── Cargo.toml │ │ │ │ ├── src — Rust 源码目录 │ │ │ │ ├── target │ │ │ │ │ ├── aarch64-unknown-linux-ohos │ │ │ │ │ │ └── release │ │ │ │ │ ├── armv7-unknown-linux-ohos │ │ │ │ │ │ └── release │ │ │ │ │ ├── x86_64-unknown-linux-ohos │ │ │ │ │ │ └── release
-
-
依赖ohos-node-bindgen crate基建,开发【鸿蒙
ArkTs N-API】原生模块。因为由ohos-node-bindgen crate间接依赖的socket2 crate不兼容【华为-鸿蒙】操作系统,所以,需要-
在
DevEco Studio工程的平级目录,克隆stuartZhang/socket2至本地,git clone [email protected]:stuartZhang/socket2.git -
将其切分支至
v0.4.xcd socket2 git checkout -q v0.4.x -
在
Cargo.toml中,局部地重写Override依赖图[dependencies] socket2 = "0.4.10" [patch.crates-io] socket2 = { path = "../../../../../socket2" }
-
-
在
src目录下,编写Rust业务逻辑处理程序。 -
安装
cargo-post工具链增补项,以使用cargo build命令支持【后置处理】程序。cargo install cargo-post -
编写
build.rs与post_build.rs构建程序,将交叉编译输出的*.so文件分别复制到模块根目录/libs/arm64-v8a,模块根目录/libs/armeabi-v7a和模块根目录/libs/x86_64文件夹内。其中,build.rs作为编译【前置处理】程序- 收集
*.so文件的位置信息 - 生成【文件复制】指令
- 将【文件复制】指令追加写入到指定的
*.cmd / *.sh文件内。
- 收集
post_build.rs作为编译【后置处理】程序- 执行【文件复制】脚本程序文件
- 删除该脚本程序文件
看图吧,一图抵千词
-
执行交叉编译指令
cargo +nightly post build --release -Zbuild-std \ --target=aarch64-unknown-linux-ohos \ --target=armv7-unknown-linux-ohos \ --target=x86_64-unknown-linux-ohos -
交叉编译输出的【链接库】文件名被自动命名为“
lib<包名>.so”。所以,若Cargo.toml定义[package] name为calculator,那么交叉编译输出的链接库文件名就是libcalculator.so。 -
在
ArkTs代码中,直接以【链接库】文件名为【ES Module模块名】导入原生模块,并执行它的成员方法。import calculator from 'libcalculator.so'; const result = calculator.add(2, 3);
总得来讲,除了Rust + N-API编程门槛着实有点高之外,剩余的工作就不难了!