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.x
cd 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
编程门槛着实有点高之外,剩余的工作就不难了!