首页 > 其他分享 >#星计划# 浅谈OpenHarmony的NDK开发

#星计划# 浅谈OpenHarmony的NDK开发

时间:2024-01-19 12:32:05浏览次数:37  
标签:OpenHarmony NDK 浅谈 ndk 接口 API napi Native

背景

Native API(NDK)入门

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

名词概念

名词 名词解释
Native API OHOS SDK里面native包提供的,面向三方应用开发的Native 接口以及相应编译脚本,编译工具链。包括C运行时基础库libc,3D图形库opengl,面向JS与C跨语言的接口Node-API等,具体内容详见下表。
NDK Native Develop Kit的缩写,在OHOS上就是Native API;Native API是官方名字,NDK指代相同意思。
SDK CAPI OHOS 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完全兼容。
napi Node-API的曾用名,当前Node-API头文件中的接口仍然以napi_开头,不建议使用。

Native API构成介绍

Native API目录结构

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

目录 功能说明
build 应用中编译动态库的toolchain cmake脚本;这个目录下ohos.toolchain.cmake文件定义了给OHOS交叉编译选项
build-tools 放置编译构建的工具,如cmake
docs Native 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-API ArkUI提供的,方便应用开发接入JS应用环境的一组类Node-API(也叫napi),是属于Native API的一部分 8
XComponent ArkUI XComponent组件中的surface与触屏事件接口,方便开发者开发高性能图形应用 8
libuv ArkUI集成的三方的异步IO库 8
libz zlib库,提供基本的压缩,解压接口 8
Drawing 系统提供的2D图形库,可以在surface进行绘制 8
OpenGL 系统提供的openglv3接口 8
Rawfile 应用资源访问接口,可以读取应用中打包的各种资源 8
OpenSLES 用于2D,3D音频加速的接口库 8
Mindspore AI模型接口库 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对应的库文件和头文件;

image.png

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

ohos的ci网址如下:每日构建 | OpenHarmony CI

image.png

使用建议

建议使用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++直接调用的接口;
  • 社区文档:https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/reference。

PS:附件是这个用例里的代码和3.2,4.0里扫出的ndk,有需要自取。

附件链接: 3.2Releasendklibgn.md 4.0ndklibgn.md MyNDKApplication.zip

本文作者:左翼风发

想了解更多关于鸿蒙的内容,请访问:​

​51CTO鸿蒙开发者社区

​https://ost.51cto.com/#bkwz​

标签:OpenHarmony,NDK,浅谈,ndk,接口,API,napi,Native
From: https://blog.51cto.com/harmonyos/9327999

相关文章

  • 以新晋高速公路快村营至营盘段项目为例浅谈AcrelEMS-HIM高速公路综合能效系统的应用
    引言摘要:我国新型工业化、信息化、城镇化和农业现代化加快发展,经济结构加快转型,交通运输总量将保持较快增长态势,各项事业发展要求提高国家公路网的服务能力和水平。高速公路沿线的收费站、互通枢纽、服务区、隧道等配置的供配电、照明、通风、排水等机电设备的数量急聚增加,设计一套......
  • 以青岛公交车停车场为例浅谈电动汽车充电站的电气安全
    1引言1月14日日上午10点左右,青岛市市北区辽宁路63号公交停车场内,一辆报废公交车突然起火,由于大风天气,大火很快引燃了停在旁边的几辆报废车。消防人员快速赶到,迅速控制住火势。11时30分,停车场内的大火已经被完全扑灭,共有8辆公交车被烧毁,没有人员伤亡。消防人员正在现场进一步勘查具......
  • #星计划# OpenHarmony NAPI技术简介
    作者:廖家兴简介NAPI(NativeAPI)是OpenHarmony系统中的一套原生模块扩展开发框架,它基于Node.jsN-API规范开发,为开发者提供了JavaScript与C/C++模块之间相互调用的交互能力。可以在NodeJs官网查看各种NAPI接口定义说明。NAPI作用OpenHarmony系统可以将框架层丰富的模块功能通过j......
  • #星计划# 浅谈OH4.0的兼容性测评
    背景OpenHarmony兼容性测评主要是验证合作伙伴的设备和业务应用满足OpenHarmony开源兼容性定义的技术要求,确保运行在OpenHarmony上的设备和业务应用能稳定、正常运行,同时使用OpenHarmony的设备和业务应用有一致性的接口和业务体验。OpenHarmony兼容性测评服务包括:产品兼容性技术......
  • 浅谈 AC 自动机
    浅谈AC自动机前言这不是第一次看到这个算法。第一次是在OI-wiki上瞄到的。当时我还是一个什么也不懂的初一蒟蒻,看到这个名字就十分兴奋:“‘AC自动机’耶!是不是可以帮我自动AC!?”后来看到只是一个字符串算法,就离开了。今天上课讲了这个,感觉原理及实现没有后缀数组那么难......
  • 浅谈电动汽车充电站箱变电气安全物联监测系统设计与应用
    摘要 摘要:基于物联网技术架构提出了一种适用于电动汽车充电站箱变的电气安全物联监测系统设计方案。该系统由电气安全智能感知设备、通信网关、电气安全物联网监测平台等构成,可支持充电站箱变充电桩出线回路电流、电缆温度、剩余电流、故障电弧、短路电流等数据采集监测,并通......
  • 浅谈 Trie 树
    浅谈Trie树什么是Trie树?Trie树,又称字典树,可用于存储单词。Trie树的根节点不表示任何字母,但是除了根节点的所有字母都表示一个字母。任何一个单词,都可以用一条从根节点出发的路径表示。在路径的终点做一个“结束”标记,对应一个单词的结尾。举个例子:要存储work,word,wo......
  • 从前端角度浅谈性能 | 京东物流技术团队
    1前言自网站诞生以来,页面白屏时间、用户交互的响应速度等一直都是开发者关心的问题,这直接影响了一个网站能否为用户的浏览提供舒适的服务,而这种舒适度,直接关系着对用户的吸引力,毕竟谁都不能忍受一个页面长达10秒的空白屏时间,更别说点击按钮后,页面长时间的毫无反应。web的性能......
  • 浅谈Linux下傻瓜式磁盘分区工具cfdisk的使用
    对于新手来说,Linux环境下的磁盘分区可能还会存在一些困难。对于熟悉Linux的朋友来说,我们还有fdisk、parted(2TB以上的磁盘分区使用)等磁盘分区工具可以使用。在我们新增磁盘或者在原来磁盘上进行扩容时就会使用到磁盘分区工具,磁盘分区对于整个系统的管理十分重要。1.增加一块容量......
  • Openharmony 跑 CV 算法
    最近有个项目,老同学让帮忙验证一个在ARM板上跑OpenHarmony,然后再集成一个CV算法上去,写这个文章主要是整理一下思路。如果有思路不对的地方,也烦请指出。1.个人做纯软件比较多,所以想着先不用板子,找个仿真环境,网上查了下,Qemu这个工具挺主流,那就先选它了,先跑起来这个(Ongoing)2.......