跳到主要内容OpenHarmony 使用 C/C++/Rust 开发原生应用指南 | 极客日志Rust
OpenHarmony 使用 C/C++/Rust 开发原生应用指南
在 OpenHarmony 操作系统中开发 C/C++ 及 Rust 原生应用的全流程。内容涵盖模块创建、BUILD.gn 与 bundle.json 配置、交叉编译环境搭建以及三方库集成。通过 Curl 网络请求和 Ansi 终端特效两个实战案例,展示了从基础 Hello World 到复杂功能实现的完整链路。特别针对 Rust 在鸿蒙系统中的交叉编译难点提供了具体的 config.toml 配置方案,解决了 linker 指向和静态链接等常见问题,适合希望深入系统底层开发的工程师参考。
晚风叙旧3 浏览 OpenHarmony 下 C/C++ 与 Rust 原生应用开发
简介
本文档主要介绍如何在 OpenHarmony 操作系统中开发 C/C++/Rust 编写的 ELF 可执行程序。这类需求通常偏向嵌入式底层应用,不涉及 ArkTS 用户界面,重点在于底层功能模块的兼容性和性能优化。
作为新一代系统级编程语言,Rust 以'内存安全、并发友好'著称,能从源头避免缓冲区溢出等安全问题。在 OpenHarmony 生态中,部分组件已采用 Rust 开发,其性能表现优异,已成为系统开发的重要选项。
ELF (Executable and Linking Format) 是 UNIX 系统实验室开发的二进制文件格式,用于可执行文件、目标代码和共享库。在 OpenHarmony 中,我们主要关注如何构建并运行此类程序。
本文将涵盖:
- OpenHarmony 系统中应用模块的添加流程
- C/C++ 代码功能实现(含网络请求示例)
- Rust 代码功能实现(含控制台特效示例)
- 常用三方库的依赖管理
第一部分 C/C++ 应用开发
一、在 OpenHarmony 中添加模块
1. 创建基础应用模板
首先需要在源码目录下的 applications/standard 路径中添加应用模块。参考官方文档进行模块结构搭建。
基本步骤如下:
- 创建目录:在源码目录下新建模块目录,例如
hello_world。
- 配置文件:创建
BUILD.gn(编译规则)和 bundle.json(元数据)。
- 入口文件:添加
main.cpp 作为应用入口。
2. 配置 BUILD.gn 文件
OpenHarmony 支持多种 GN 模板,开发应用程序需使用 ohos_executable。核心配置项包括源文件、头文件路径、依赖及安装路径。
import("//build/ohos.gni")
ohos_executable("hello_world") {
sources = [ "src/main.cpp" ]
include_dirs = [ "src/include" ]
output_name = "hello_world"
install_enable = true
subsystem_name = "applications"
part_name = "hello_world"
external_deps = [ ]
deps = [ ]
}
同时需要更新 bundle.json 以注册组件信息:
{
"name": "@ohos/hello_world",
"description": "hello world example",
"version": "3.1",
"license": "Apache License 2.0"
,
"publishAs"
:
"code-segment"
,
"segment"
:
{
"destPath"
:
"hello_world"
}
,
"component"
:
{
"name"
:
"hello_world"
,
"subsystem"
:
"applications"
,
"adapted_system_type"
:
[
"mini"
,
"small"
,
"standard"
]
,
"deps"
:
{
"components"
:
[
]
,
"third_party"
:
[
]
}
,
"build"
:
{
"sub_component"
:
[
"//applications/standard/hello_world:hello_world"
]
}
}
}
最后,在产品配置 config.json 中添加该组件,确保子系统识别。
3. 编写代码与编译
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
./build.sh --product-name rk3568 --build-target applications/standard/hello_world:hello_world
编译成功后,在 output 目录下找到可执行文件,通过 hdc 推送到开发板运行:
hdc file send output/hello_world /data
hdc shell /data/hello_world
二、实现简单网络请求功能
为了演示实际功能,我们可以引入 curl 库实现 HTTP GET 请求。OpenHarmony 系统源码中已提供丰富的三方库,直接在 BUILD.gn 中声明依赖即可。
在 BUILD.gn 中添加 curl 依赖及链接标志:
external_deps = [ "curl:curl_shared" ]
ldflags = [ "-lrt", "-lpthread", "-ldl" ]
并在 bundle.json 的 deps 中声明组件依赖。
#include <iostream>
#include <curl/curl.h>
#include <string>
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* response) {
size_t totalSize = size * nmemb;
response->append((char*)contents, totalSize);
return totalSize;
}
int main(int argc, char const *argv[]) {
CURL* curl = curl_easy_init();
if (!curl) {
std::cout << "初始化 curl 失败" << std::endl;
return -1;
}
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, "http://www.baidu.com");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cout << "curl 请求失败:" << curl_easy_strerror(res) << std::endl;
} else {
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
std::cout << "HTTP 状态码:" << http_code << std::endl;
std::cout << "响应内容预览:" << std::endl;
std::cout << response.substr(0, 200) << "..." << std::endl;
}
curl_easy_cleanup(curl);
return 0;
}
第二部分 Rust 应用开发
一、在 OpenHarmony 中添加模块
Rust 应用模块结构与 C/C++ 类似,但增加了 Cargo.toml 用于管理依赖。
1. 目录结构
├── src
│ ├── main.rs
│ ├── BUILD.gn
│ └── bundle.json
└── Cargo.toml
在 applications/standard 下创建 hello_world_rs 目录,并使用 cargo init 生成基础项目。
2. 配置 BUILD.gn 与 Cargo.toml
Rust 的可执行文件模板为 ohos_rust_executable。配置 BUILD.gn 时需注意指定源文件路径及禁用部分检查警告。
import("//build/ohos.gni")
ohos_rust_executable("hello_world_rs") {
sources = [ "src/main.rs" ]
output_name = "hello_world_rs"
rustflags = [ "-A", "missing-docs" ]
}
[package]
name = "hello_world_rs"
version = "0.1.0"
edition = "2021"
产品配置 config.json 中同样需要注册该组件。
3. 交叉编译与环境配置
Rust 在 OpenHarmony 中依赖特定的交叉编译链。虽然 rustup 提供了 target,但需手动指定 linker 以匹配 OHOS SDK。
在工程根目录创建 .cargo/config.toml:
[target.aarch64-unknown-linux-ohos]
linker = "你的 ohos_sdk 路径/native/llvm/bin/aarch64-unknown-linux-ohos-clang"
ar = "你的 ohos_sdk 路径/native/llvm/bin/llvm-ar"
[build]
target = "aarch64-unknown-linux-musl"
rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-static" ]
注意:请将上述路径替换为你实际的 SDK 路径。静态链接配置有助于减少运行时依赖问题。
cargo build --target=aarch64-unknown-linux-ohos --release
生成的可执行文件位于 target/aarch64-unknown-linux-ohos/release/ 目录下。
二、实现 Rust 功能示例
为了展示 Rust 的控制台能力,我们引入 ansi_term 库来实现带颜色的终端输出。
[dependencies]
ansi_term = "0.12"
use ansi_term::Colour;
use ansi_term::Style;
use std::panic;
use std::backtrace::Backtrace;
use std::thread;
use std::time::Duration;
fn print_title(text: &str) {
let title_style = Style::new()
.bold()
.on(Colour::RGB(40, 44, 52))
.fg(Colour::RGB(97, 175, 239));
let border = "─".repeat(text.len() + 4);
println!("\n{}", Colour::RGB(86, 182, 194).paint(format!("╔{}╗", border)));
println!("║{}║", title_style.paint(format!(" {} ", text)));
println!("{}\n", Colour::RGB(86, 182, 194).paint(format!("╚{}╝", border)));
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
panic::set_hook(Box::new(|panic_info| {
print_title("🚨 PANIC 发生 🚨");
if let Some(location) = panic_info.location() {
println!("位置:{}:{}:{}", location.file(), location.line(), location.column());
}
print_title("🛑 PANIC 结束 🛑");
}));
print_title("🚀 Rust 炫酷控制台演示程序 🚀");
println!("欢迎体验 ANSI 终端效果!");
for i in 1..=5 {
let percentage = (i as f32 / 5.0 * 100.0) as u32;
let bar = format!("[{}]", "█".repeat(i) + &"░".repeat(5 - i));
println!("{} {}% 执行步骤 {}/5",
Colour::RGB(152, 195, 121).paint(bar),
Colour::RGB(229, 192, 123).paint(percentage.to_string()),
i);
thread::sleep(Duration::from_millis(800));
}
print_title("🎉 演示完成");
Ok(())
}
编译后推入设备,添加执行权限 (chmod +x) 即可运行。可以看到彩色的控制台输出效果。
常见问题与注意事项
Q: OpenHarmony 中如何操作 GPIO 和串口?
建议查阅 OpenHarmony 官方开发者文档中的硬件抽象层(HAL)相关章节,或参考官方提供的示例 Demo 获取 API 调用方式。
Q: 如果所需三方库未在系统中实现,该如何移植?
可参考 OpenHarmony SIG 社区发布的 C/C++ 三方库移植适配指导说明。对于 Rust 库,由于构建系统差异(GN vs Cargo),通常需要自行转换或寻找适配后的版本。
Q: 能否直接使用 Cargo 管理依赖?
OpenHarmony 原生构建基于 GN,不直接支持 Cargo 构建流程。虽然有 Cargo2GN 工具,但由于依赖传递复杂,建议优先使用 GN 管理依赖,或在 Rust 项目中通过 Cargo.toml 管理源码依赖,再通过 GN 调用编译产物。
提示:全量编译系统烧录后,可直接在 Shell 中通过命令运行 hello_world 或 hello_world_rs。
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online