【鸿蒙南向开发】浅谈OpenHarmony4.0的NDK开发

199 篇文章 8 订阅
198 篇文章 0 订阅

背景

Native API(NDK)入门

Native API 是 OpenHarmony SDK 上提供的一组 native 开发接口与工具集合(也称为 NDK),方便开发者使用 C 或者 C++ 语言实现应用的关键功能。Native API 只覆盖了 OHOS 基础的一些底层能力,如 libc,图形库,窗口系统,多媒体,压缩库等,并没有完全提供类似于 JS API 上的完整的 OHOS 平台能力。在应用中使用 Native API 会编译成动态库打包到应用中。

名词概念
名词名词解释
Native APIOHOS SDK 里面 native 包提供的,面向三方应用开发的 Native 接口以及相应编译脚本,编译工具链。包括 C 运行时基础库 libc,3D 图形库 opengl,面向 JS 与 C 跨语言的接口 Node-API 等,具体内容详见下表。
NDKNative Develop Kit 的缩写,在 OHOS 上就是 Native API;Native API 是官方名字,NDK 指代相同意思。
SDK CAPIOHOS Native API 中的 C 语言接口,以及工具链部分,当前 OHOS 的 Native API 里面只包含 C 语言接口,因此 Native API 与 CAPI 意思一样,建议交流的时候使用 CAPI,防止 Native API 与 napi 缩写混用。
Node-API曾用名 napi,是 OHOS 中提供 JS 与 C 跨语言调用的接口,是 Native API 接口中的一部分. 该接口在 Node.js 提供的 Node-API 基础上扩展而来,但不完全与 Node.js 中的 Node-API 完全兼容。
napiNode-API 的曾用名,当前 Node-API 头文件中的接口仍然以 napi_开头,不建议使用。

Native API 构成介绍

Native API 目录结构

Native API 在 SDK 包的位置为$(SDK_ROOT)/native 目录,主要有以下几个部分组成

目录功能说明
build应用中编译动态库的 toolchain cmake 脚本;这个目录下 ohos.toolchain.cmake 文件定义了给 OHOS 交叉编译选项
build-tools放置编译构建的工具,如 cmake
docsNative API 接口参考文档,通过 doxgen 从头文件中提取出来
llvm支持 OHOS ABI 的 llvm 交叉编译器
sysroot放置编译链接的依赖文件目录,包含头文件,动态库等

Native API 接口(4.0 Release)

接口分类接口功能引入版本
标准 C 库以 musl 为基础提供的标准 c 库接口,当前提供了 1500+ 的接口8
标准 C++ 库c++ 运行时库 libc++_shared,此库在打包的时候需要打包或者静态链接到应用中8
日志打印日志到系统的 hilog 接口8
Node-APIArkUI 提供的,方便应用开发接入 JS 应用环境的一组类 Node-API(也叫 napi),是属于 Native API 的一部分8
XComponentArkUI XComponent 组件中的 surface 与触屏事件接口,方便开发者开发高性能图形应用8
libuvArkUI 集成的三方的异步 IO 库8
libzzlib 库,提供基本的压缩,解压接口8
Drawing系统提供的 2D 图形库,可以在 surface 进行绘制8
OpenGL系统提供的 openglv3 接口8
Rawfile应用资源访问接口,可以读取应用中打包的各种资源8
OpenSLES用于 2D,3D 音频加速的接口库8
MindsporeAI 模型接口库9
包管理包服务接口,方便查询应用包信息8

Native API 相关资料

简单应用

如何开发应用?
  • DevEco IDE 创建工程选择“Native C++”模板:

    image.png

image.png

**编译运行后,点击 helloworld 打印输出有:Test NAPI 2 + 3 = 5**
  • ArkUI 部分:

    import hilog from '@ohos.hilog';           //导入hilog
    import testNapi from 'libentry.so';        //导入nativeC++模块
    
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World';
    
      build() {
        Row() {
          Column() {
            Text(this.message)
              .fontSize(50)
              .fontWeight(FontWeight.Bold)
              .onClick(() => {
                //调用nativeC++代码
                hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
              })
          }
          .width('100%')
        }
        .height('100%')
      }
    }
    
    
  • nativeC++ 部分由 CMake 和 C++ 代码两部分组成:

    • CMake:

      # the minimum version of CMake.
      cmake_minimum_required(VERSION 3.4.1)
      project(MyNDKApplication)
      # 编译路径
      set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
      # 编译头文件路径
      include_directories(${NATIVERENDER_ROOT_PATH}
                          ${NATIVERENDER_ROOT_PATH}/include)
      # 编译对象entry是对应用层可见的so,即import testNapi from 'libentry.so'
      add_library(entry SHARED hello.cpp)
      # 这是link命令,libace_napi 这个就是node-api需要用的so库;
      target_link_libraries(entry PUBLIC libace_napi.z.so)
      
      
    • C++:

      #include "napi/native_api.h"
      // 对外node-api方法,对应testNapi.add(2, 3)
      static napi_value Add(napi_env env, napi_callback_info info)
      {
          size_t requireArgc = 2;
          size_t argc = 2;
          napi_value args[2] = {nullptr};
      
          napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
      
          napi_valuetype valuetype0;
          napi_typeof(env, args[0], &valuetype0);
      
          napi_valuetype valuetype1;
          napi_typeof(env, args[1], &valuetype1);
      
          double value0;
          napi_get_value_double(env, args[0], &value0);
      
          double value1;
          napi_get_value_double(env, args[1], &value1);
      
          napi_value sum;
          napi_create_double(env, value0 + value1, &sum);
      
          return sum;
      
      }
      // 模块初始化方法,对应的方法在这加入对外描述队列
      EXTERN_C_START
      static napi_value Init(napi_env env, napi_value exports)
      {
          napi_property_descriptor desc[] = {
              { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
          };
          napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
          return exports;
      }
      EXTERN_C_END
      // 模块声明,import时候调用
      static napi_module demoModule = {
          .nm_version = 1,
          .nm_flags = 0,
          .nm_filename = nullptr,
          .nm_register_func = Init,
          .nm_modname = "entry",
          .nm_priv = ((void*)0),
          .reserved = { 0 },
      };
      // 模块入口注册
      extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
      {
          napi_module_register(&demoModule);
      }
      
      
如何使用系统 NDK?

上面例子运行起来后,c++ 部分是没有打印信息的,若想看到对应的打印信息,则需要调用 hilog 进行输出,修改如下:

  • cmake 修改:

    # the minimum version of CMake.
    cmake_minimum_required(VERSION 3.4.1)
    project(MyNDKApplication)
    
    set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
    
    include_directories(${NATIVERENDER_ROOT_PATH}
                        ${NATIVERENDER_ROOT_PATH}/include)
    # 增加hiloglib库引用
    find_library(
        # Sets the name of the path variable.
        hilog-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        hilog_ndk.z
    )
    
    add_library(entry SHARED hello.cpp)
    # 增加hiloglib库连接
    target_link_libraries(entry PUBLIC ${hilog-lib} libace_napi.z.so)
    
    
  • c++ 文件修改:

    // 增加hilog头文件
    #include <hilog/log.h>
    #include "napi/native_api.h"
    
    static napi_value Add(napi_env env, napi_callback_info info)
    {
        // 增加打印输出
        const unsigned int LOG_PRINT_DOMAIN = 0xFF00;
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Init", "Init begins");
        size_t requireArgc = 2;
        size_t argc = 2;
        napi_value args[2] = {nullptr};
    
    ...
    
    
  • 输出:

    08-07 05:40:25.079  15167-15167  A0ff00/Init                    com.example.myndkapplication    I  Init begins
    08-07 05:40:25.079  15167-15167  A00000/testTag                 com.example.myndkapplication    I  Test NAPI 2 + 3 = 5
    
    
具体原理是什么?

1、PC 端 OHOS SDK 里包括了 native 对应的库文件和头文件;

2、OHOS 源码可以编译出带 NDK 的 FullSDK,也可以从 CI 网址下载;

# Generate NDK library from NDK description file.
#
# Variables:
#  ndk_description_file:
#  min_compact_version: string specifies the minimal compactible version of NDK.
#    set to major_version in default.
#
template("ohos_ndk_library") {
  forward_variables_from(invoker, [ "testonly" ])
  assert(defined(invoker.ndk_description_file),
         "ndk description file is necessary ")
...
// 在GN里用ohos_ndk_library生成ndk库和头文件,如

ohos_ndk_library("libhilog_ndk") {
  output_name = "hilog_ndk"
  ndk_description_file = "./libhilog.ndk.json"
  min_compact_version = "1"
  system_capability = "SystemCapability.HiviewDFX.HiLog"
}

ohos_ndk_headers("hilog_header") {
  dest_dir = "$ndk_headers_out_dir/hilog"
  sources = [ "./include/hilog/log.h" ]
} 

// ndk_description_file 对应的 libhilog.ndk.json 文件里声明了导出的接口函数
[
    {
        "name": "OH_LOG_Print"
    },
    {
        "name": "OH_LOG_IsLoggable"
    }
]

// ohos 编译fullsdk的命令: ./build.sh --product-name ohos-sdk

使用建议

建议使用 Native API 的场景

主要有如下一些

  1. 应用性能敏感代码,比如游戏,物理模拟等计算密集型场景
  2. 需要复用已有的 C 或 C++ 库
  3. 需要针对 CPU 特性进行专项定制的库,如 neon 加速
不建议使用 Native API 的场景
  1. 写一个纯 native 的的 OHOS 应用
  2. 希望在尽可能多的 OHOS 设备上保持兼容的应用
维测能力
  1. OHOS 官方提供 lldb remote 方式代码调试,详细参看lldb 参考手册
  2. musl 库的 log 维测能力,请参看libc 库维测章节。

总结

  • NDK 方式是应用层直接调用底层库或者三方库目前看最常规的方式;
  • 4.0(API10)有 ndk 46 个,3.2(API9)有 ndk 28 个,实质代码里有更多的 ndk,RK 的原因没有编出更多,比如 sensor 部分就没有编译出来;
  • 划重点,NDK 里有两种 api:node-api,用于 arkts 和 c++ 调用和传递数据;c/c++ api,可以把动态库打包成应用侧 c++ 直接调用的接口;

写在最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。

这份鸿蒙(HarmonyOS NEXT)文档包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习文档能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习文档

鸿蒙(HarmonyOS NEXT)5.0最新学习路线

在这里插入图片描述

有了路线图,怎么能没有学习文档呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习文档

《鸿蒙 (OpenHarmony)开发入门教学视频》

在这里插入图片描述

《鸿蒙生态应用开发V3.0白皮书》

在这里插入图片描述

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

在这里插入图片描述

《鸿蒙开发基础》

●ArkTS语言
●安装DevEco Studio
●运用你的第一个ArkTS应用
●ArkUI声明式UI开发
.……
在这里插入图片描述

《鸿蒙开发进阶》

●Stage模型入门
●网络管理
●数据管理
●电话服务
●分布式应用开发
●通知与窗口管理
●多媒体技术
●安全技能
●任务管理
●WebGL
●国际化开发
●应用测试
●DFX面向未来设计
●鸿蒙系统移植和裁剪定制
……
在这里插入图片描述

《鸿蒙进阶实战》

●ArkTS实践
●UIAbility应用
●网络案例
……
在这里插入图片描述

获取以上完整鸿蒙HarmonyOS学习文档,请点击→纯血版全套鸿蒙HarmonyOS学习文档

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值