天天看點

#沖刺創作新星# #跟着小白一起學鴻蒙# [七] 寫個NAPI子系統

作者:王石

在《#跟着小白一起學鴻蒙#[六]第一個hap應用》我們熟悉了如何在開源鴻蒙開發hap應用,後期的文章我們會寫在hap應用裡調用系統庫甚至是動态庫。此篇文章,我們主要是熟悉下NAPI架構,并一起寫一個支援NAPI的子系統,這樣以後當我們想在hap應用裡加自己功能的時候就可以友善的添加。

NAPI架構簡介

NAPI(Native API)元件是一套對外接口基于Node.js N-API規範開發的原生子產品擴充開發架構。類似于Android的JNI,NAPI架構實作了應用層ts/ets/js語言編寫的代碼和開源鴻蒙的native代碼(c/c++)互動的能力。此架構由Node.js N-API架構擴充而來。

注意:開源鴻蒙的标準系統是采用NAPI架構的,輕量系統則是采用jerryscript架構

#沖刺創作新星# #跟着小白一起學鴻蒙# [七] 寫個NAPI子系統

詳細的内容介紹在一下連結内可以看到官方的說明:

參考連結:https://gitee.com/openharmony/arkui_napi

NAPI的使用

graph LR
建立d.ts --> 執行napi_generator --> 建立子系統 --> 引入子系統 --> 編譯生成
           
  1. 建立d.ts: @ohos.napitest.d.ts, basic.d.ts
    • @ohos.napitest.d.ts是NAPI的聲明檔案,在DevEco Studio開發的時候會用到d.ts來檢查文法和提供代碼幫助;
    import {AsyncCallback} from './basic';
    
    /**
     * Provides interfaces to napitest.
     *
     * @since 7
     */
    declare namespace napitest {
      /**
       * Shuts down the system.
       *
       * <p>This method requires the ohos.permission.SHUTDOWN permission.
       *
       * @param reason Indicates the shutdown reason.
       * @systemapi
       * @since 7
       */
      function shutdownDevice(reason: string): void;
    
      /**
       * Restarts the system.
       *
       * <p>This method requires the ohos.permission.REBOOT permission.
       *
       * @param reason Indicates the restart reason. For example, "updater" indicates entering the updater mode
       * after the restart. If the parameter is not specified, the system enters the normal mode after the restart.
       * @since 7
       */
      function rebootDevice(reason: string): void;
    
      /**
       * Checks whether the screen of a device is on or off.
       *
       * @return Returns true if the screen is on; returns false otherwise.
       * @since 7
       */
      function isScreenOn(callback: AsyncCallback<boolean>): void;
      function isScreenOn(): Promise<boolean>;
    }
    export default napitest;
               
    • basic.d.ts:一些基礎方法的聲明
    export interface Callback<T> {
        (data: T): void;
    }
      
    export interface ErrorCallback<T extends Error = BusinessError> {
        (err: T): void;
    }
    
    export interface AsyncCallback<T> {
        (err: BusinessError, data: T): void;
    }
    
    export interface BusinessError extends Error {
        code: number;
    }
               
  2. 執行napi_generator

    建立個檔案夾,将上面建立的兩個d.ts和napi_generator放在一起

    //準備環境
    mkdir napitest
    cd napitest
    vim @ohos.napitest.d.ts
    vim basic.d.ts
    //拷貝napi_generator
    cp [路徑]/napi_generator-linux .
    chmod +x napi_generator-linux
    //生成napitest代碼
    ./napi_generator-linux -f @ohos.napitest.d.ts -o out
    //當看到success則說明燒錄成功
    
    //檢視out目錄
    ├── binding.gyp			//工具中間檔案
    ├── BUILD.gn			//之後需要用到的gn檔案
    ├── napi_gen.log		//工具log
    ├── napitest.cpp		//自動生成的接口調用的實際代碼
    ├── napitest.h			//自動生成的接口調用的實際代碼
    ├── napitest_middle.cpp	//自動生成的napi适配代碼
    ├── test.sh				//生成js代碼的腳本,官方沒給說明,試了下不可用
    ├── tool_utility.cpp	//自動生成的napi适配代碼
    └── tool_utility.h		//自動生成的napi适配代碼
               
  3. 建立子系統
    • 在鴻蒙源碼目錄下建立foundation/napitest,将之前生成的檔案拷貝到檔案夾内
    foundation
    ├── ability
    ├── ai
    ├── arkui
    ├── barrierfree
    ├── bundlemanager
    ├── communication
    ├── deviceprofile
    ├── distributeddatamgr
    ├── distributedhardware
    ├── filemanagement
    ├── graphic
    ├── multimedia
    ├── multimodalinput
    ├── napitest
    │   ├── binding.gyp
    │   ├── BUILD.gn
    │   ├── bundle.json
    │   ├── napi_gen.log
    │   ├── napitest.cpp
    │   ├── napitest.h
    │   ├── napitest_middle.cpp
    │   ├── test.sh
    │   ├── tool_utility.cpp
    │   └── tool_utility.h
    ├── resourceschedule
               
    • 在目錄裡建立bundle.json,使用一下内容
    {
        "name": "@ohos/napitest",
        "description": "napitest provides atomic capabilities",
        "version": "3.1",
        "license": "Apache License 2.0",
        "publishAs": "code-segment",
        "segment": {
          "destPath": "foundation/napitest"
        },
        "dirs": {},
        "scripts": {},
        "component": {
          //部件名稱
          "name": "napitest_interface",
          //子系統名稱
          "subsystem": "napitest",
          "features": [],
          "adapted_system_type": [
            "standard"
          ],
          "rom": "10000KB",
          "ram": "10000KB",
          "deps": {
            "components": [
              "ace_napi",
              "ipc_core",
              "libhilog"
            ],
            "third_party": [
              "node"
            ]
          },
          "build": {
            "sub_component": [
              "//foundation/napitest:napitest"
            ],
            "inner_kits": [
              {
                "header": {
                  "header_base": "//foundation/napitest",
                  "header_files": [
                    "tool_utility.h",
                    "napitest.h"
                  ]
                },
                "name": "//foundation/napitest:napitest"
              }
            ]
          }
        }
      }
               
    • 為了和bundle.json對應,将BUILD.gn改成如下:
    import("//build/ohos.gni")
    
    ohos_shared_library("napitest")
    {
        sources = [
            "napitest_middle.cpp",
            "napitest.cpp",
            "tool_utility.cpp",
        ]
        include_dirs = [
            ".",
            "//third_party/node/src",
            "//base/hiviewdfx/hilog/interfaces/native/innerkits/include",
        ]
        deps=[
            "//foundation/arkui/napi:ace_napi",
            "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog",
        ]
        remove_configs = [ "//build/config/compiler:no_rtti" ]
        cflags=[
        ]
        cflags_cc=[
            "-frtti",
        ]
        ldflags = [
        ]
        
        relative_install_dir = "module"
    	//部件名稱
        part_name = "napitest_interface"
    	//子系統名稱
        subsystem_name = "napitest"
    }
               
  4. 引入子系統
    • 增加子系統,修改build/subsystem_config.json
      //在檔案後增加
      {
        //前面省略的内容
      	...
        //新增内容
        "napitest": {
          "path": "foundation/napitest",
          "name": "napitest"
        }
      }
                 
    • 增加編譯入口(已目前的master版本為基礎,3.2後改過編譯路徑)
      //修改 vendor/hihope/[PRODUCT_NAME]/config.json 檔案增加如下行
      {
      	"subsystem": "napitest",
      	"components": [
      	{
      		"component": "napitest_interface",
      		"features": []
      	}
      	]
      },
                 
  5. 編譯生成
    ./build.sh --product-name PRODUCT_NAME
    //看到success則為編譯成功,可以通過find out/[PRODUCT_NAME] -name *napitest.z.so檢視生成檔案,比如我的檔案路徑如下:
    ./out/rk3568/lib.unstripped/napitest/napitest_interface/libnapitest.z.so
    ./out/rk3568/napitest/napitest_interface/libnapitest.z.so
    ./out/rk3568/innerkits/ohos-arm/napitest_interface/napitest/libnapitest.z.so
    ./out/rk3568/packages/phone/system/lib/module/libnapitest.z.so
    //最後一個路徑就是系統鏡像的路徑,是以兩種辦法
    //1,直接copy到闆子的/system/lib路徑;參考《#跟着小白一起學鴻蒙# [二]第一個OpenHarmony程式》
    //2,燒錄鏡像;參考《#跟着小白一起學鴻蒙# [一]運作OpenHarmony》
    
    
               

總結

這樣我們就有了自己的subsystem和napi接口,後面的章節我們會講如何在hap應用裡調用系統庫

參考連結:https://gitee.com/openharmony/napi_generator/tree/master

附件連結:https://ost.51cto.com/resource/2308

繼續閱讀