鸿蒙ArkTS 与 Native 交互场景分类总结与关键实现

Native侧跨HAR/HSP模块接口调用-程序包结构-应用框架 - 华为HarmonyOS开发者

ArkTS 与 Native 交互场景分类总结与关键实现

一、场景分类总结

场景类型 调用方向 适用场景 技术特点
ArkTS → Native HAP ArkTS → 同模块 Native 高性能计算、硬件操作 使用 Node-API 直接调用
Native → Native HAP Native → HAR/HSP Native 跨模块复用底层能力 头文件导出 + SO 链接
Native → ArkTS HAR/HSP Native → 同模块 ArkTS Native 回调业务逻辑 napi_load_module 动态加载

二、关键代码流程详解

场景1:ArkTS 调用同模块 Native

调用链 ​:HAP ArkTS → HAP Native

关键流程​:

javascript 复制代码
// ArkTS 侧 (index.ets)
import napi from 'libentry.so'

Button('调用Native方法').onClick(() => {
  const result = napi.add(2, 3) // 调用Native方法
})
scss 复制代码
// Native 侧 (napi_init.cpp)
static napi_value Add(napi_env env, napi_callback_info info) {
  // 1. 解析参数
  size_t argc = 2;
  napi_value args[2];
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
  
  // 2. 类型转换
  double value0, value1;
  napi_get_value_double(env, args[0], &value0);
  napi_get_value_double(env, args[1], &value1);
  
  // 3. 执行计算
  double sum = value0 + value1;
  
  // 4. 返回结果
  napi_value result;
  napi_create_double(env, sum, &result);
  return result;
}

场景2:跨模块 Native 调用

调用链 ​:HAP Native → HAR/HSP Native

关键流程​:

arduino 复制代码
// 被调用方 (HAR/HSP模块)
// napi_har.h
#pragma once
double harNativeAdd(double a, double b);

// napi_har.cpp
double harNativeAdd(double a, double b) {
  return a + b;
}
scss 复制代码
// 调用方 (HAP模块)
#include "napi_har.h" // 包含被调用方头文件

static napi_value invokeHarNative(napi_env env, napi_callback_info info) {
  // 直接调用跨模块函数
  double result = harNativeAdd(2, 3);
  
  napi_value sum;
  napi_create_double(env, result, &sum);
  return sum;
}

场景3:Native 调用 ArkTS

调用链 ​:HAR/HSP Native → 同模块 ArkTS

关键流程​:

typescript 复制代码
// ArkTS 侧 (Util.ets)
export function add(a: number, b: number): number {
  return a + b;
}
arduino 复制代码
// Native 侧 (napi_har.cpp)
napi_value harArkTSAdd(double a, double b) {
  // 1. 加载ArkTS模块
  napi_value module;
  napi_load_module_with_info(env, 
    "static_module/src/main/ets/utils/Util", // 模块路径
    "com.example.app/entry",                // 包名/模块名
    &module);
  
  // 2. 获取函数引用
  napi_value addFunc;
  napi_get_named_property(env, module, "add", &addFunc);
  
  // 3. 准备参数
  napi_value argv[2];
  napi_create_double(env, a, &argv[0]);
  napi_create_double(env, b, &argv[1]);
  
  // 4. 调用函数
  napi_value result;
  napi_call_function(env, module, addFunc, 2, argv, &result);
  return result;
}

三、CMake 配置精要

1. 被调用方 (HAR/HSP) 配置

scss 复制代码
# CMakeLists.txt (HAR/HSP模块)
add_library(native_har SHARED
    napi_har.cpp
    napi_init.cpp)

# 设置头文件搜索路径
target_include_directories(native_har PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR})
json 复制代码
// build-profile.json5 (关键导出配置)
{
  "buildOption": {
    "nativeLib": {
      "headerPath": "./src/main/cpp" // 暴露头文件
    }
  }
}

2. 调用方 (HAP) 配置

bash 复制代码
# CMakeLists.txt (HAP模块)
add_library(entry SHARED napi_init.cpp)

# 关键:链接被调用方库
target_link_libraries(entry PUBLIC
    native_har)  # 被调用方模块名::库名

# 包含被调用方头文件
target_include_directories(entry PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}
    path/to/har_module/headers)
json 复制代码
// oh-package.json5 (模块依赖声明)
{
  "dependencies": {
    "native_har": "file:../native_har_module"
  }
}

四、特殊场景处理技巧

  1. 环境传递(Native 调用 ArkTS 前置条件)
java 复制代码
// HAP Native 初始化时传递环境
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
  setHarEnv(env); // 将env传递给HAR模块
  return exports;
}
EXTERN_C_END
  1. HSP/HAR 路径差异处理
arduino 复制代码
// HSP模块使用自身模块名
napi_load_module_with_info(env,
    "hsp_module/src/main/ets/MainPage",  // 实际模块名
    "com.example.app/hsp_entry",         // 包名/模块名
    &module);
  1. 解决模块加载失败
json 复制代码
// build-profile.json5 添加运行时包声明
"buildOption": {
  "arkOptions": {
    "runtimeOnly": {
      "packages": ["native_har"] // 声明依赖包
    }
  }
}

五、最佳实践建议

  1. 头文件管理​:

    • 使用 #pragma once防止重复包含
    • 为跨模块接口创建专用头文件目录
  2. 符号导出控制​:

    • 使用 __attribute__((visibility("default")))显式导出函数
    arduino 复制代码
    __attribute__((visibility("default"))) 
    double harNativeAdd(double a, double b);
  3. 错误处理增强​:

ini 复制代码
napi_status status = napi_load_module_with_info(...);
if (status != napi_ok) {
  napi_throw_error(env, "MODULE_LOAD_FAIL", "Failed to load ArkTS module");
  return nullptr;
}
  1. 性能优化​:

    • 缓存频繁调用的 ArkTS 函数引用
    • 避免在循环中频繁加载模块

关键点总结:跨模块通信的核心在于头文件导出SO链接配置环境传递。对于Native调用ArkTS,需特别注意模块路径的正确性和运行环境的传递。

相关推荐
爱笑的眼睛116 小时前
HarmonyOS TextArea 组件:文本输入区域的简单使用指南
华为·harmonyos
前端世界6 小时前
鸿蒙异步处理从入门到实战:Promise、async/await、并发池、超时重试全套攻略
华为·harmonyos
祥睿夫子8 小时前
鸿蒙ArkTS开发:Number、Boolean、String三种核心基本数据类型详解(附实战案例)
harmonyos·arkts
小喷友8 小时前
第5章 高级UI与动画
前端·app·harmonyos
爱笑的眼睛118 小时前
HarmonyOS 递归实战:文件夹文件统计案例解析
华为·harmonyos
鸿蒙小白龙9 小时前
openharmony之启动恢复子系统详解
harmonyos·鸿蒙·鸿蒙系统
GeniuswongAir12 小时前
交叉编译.so到鸿蒙使用
华为·harmonyos
keepDXRcuriosity14 小时前
ArkTS 语言全方位解析:鸿蒙生态开发新选择
华为·harmonyos·arkts·鸿蒙
whysqwhw14 小时前
鸿蒙图标快捷菜单
harmonyos