• Home
Name Date Size #Lines LOC

..--

callback_scope_manager/12-May-2024-14591

figures/12-May-2024-

interfaces/12-May-2024-343234

module_manager/12-May-2024-907715

native_engine/12-May-2024-24,49418,341

reference_manager/12-May-2024-9452

sample/12-May-2024-13,9728,822

scope_manager/12-May-2024-552460

test/unittest/12-May-2024-3,2822,322

utils/12-May-2024-198101

.clang-formatD12-May-20243 KiB107106

.gitattributesD12-May-2024631 1615

BUILD.gnD12-May-202411.3 KiB365321

LICENSED12-May-20249.9 KiB177150

OAT.xmlD12-May-20244 KiB7016

README.mdD12-May-202412.5 KiB273226

README_zh.mdD12-May-202411.6 KiB273226

bundle.jsonD12-May-20242.7 KiB8584

libnapi.ndk.jsonD12-May-20244.5 KiB120120

napi.gniD12-May-20241.5 KiB3330

ohos.buildD12-May-20241.1 KiB4443

README.md

1# NAPI<a name="EN-US_TOPIC_0000001149901711"></a>
2
3-   [Introduction](#section11660541593)
4-   [Directory Structure](#section161941989596)
5-   [When to Use](#section11759141594811)
6-   [Available APIs](#section1611515555510)
7-   [How to Develop](#section937267212)
8-   [Repositories Involved](#section3970193518214)
9
10## Introduction<a name="section11660541593"></a>
11
12The  **foundation/arkui/napi**  repository contains a development framework for extending the JS Native Module and provides APIs developed based on Node.js N-API for external use.
13
14**Figure  1**  Architecture<a name="fig1049423884819"></a>
15
16
17![](figures/en-us_image_0000001162437581.jpg)
18
19-   **NativeEngine**
20
21    NativeEngine is the JS engine abstraction layer. It unifies API behavior of the JS engines at the NAPI layer.
22
23-   **ModuleManager**
24
25    ModuleManager is used to load modules and cache module information.
26
27-   **ScopeManager**
28
29    ScopeManager manages the NativeValue lifecycle.
30
31-   **ReferenceManager**
32
33    ReferenceManager manages the NativeReference lifecycle.
34
35
36## Directory Structure<a name="section161941989596"></a>
37
38The source code directory structure of this repository is as follows:
39
40```
41foundation/arkui/napi
42   ├── interfaces
43   │   └── kits
44   │       └── napi           # NAPI header files
45   ├── module_manager         # Module manager
46   ├── native_engine          # NativeEngine abstraction layer
47   │   └── impl
48   │       └── ark            # Ark-based NativeEngine implementation
49   ├── scope_manager          # Scope manager
50   └── test                   # Test code
51```
52
53## When to Use<a name="section11759141594811"></a>
54
55NAPI is suitable for processing I/O- and CPU-intensive tasks and system tasks. It encapsulates the capabilities and provides them to apps as JS APIs. NAPI can be used to implement mutual access between JS and C/C++ code. You can use NAPI to develop modules such as network communications, serial port access, multimedia decoding, and sensor data collection.
56
57## Available APIs<a name="section1611515555510"></a>
58
59For details about the API implementation, see the  **foundation/arkui/napi**  repository.
60
61**Table  1**  Available NAPIs
62
63<a name="table10789351555"></a>
64<table><thead align="left"><tr id="row1878635175515"><th class="cellrowborder" valign="top" width="19.439999999999998%" id="mcps1.2.3.1.1"><p id="p27816352556"><a name="p27816352556"></a><a name="p27816352556"></a>Category</p>
65</th>
66<th class="cellrowborder" valign="top" width="80.56%" id="mcps1.2.3.1.2"><p id="p078835105514"><a name="p078835105514"></a><a name="p078835105514"></a>Description</p>
67</th>
68</tr>
69</thead>
70<tbody><tr id="row17863535520"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p678143512552"><a name="p678143512552"></a><a name="p678143512552"></a>Module registration</p>
71</td>
72<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p4781035185515"><a name="p4781035185515"></a><a name="p4781035185515"></a>Registers module information with a manager.</p>
73</td>
74</tr>
75<tr id="row67951538205618"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p127961438195616"><a name="p127961438195616"></a><a name="p127961438195616"></a>Exception &amp; Error handling</p>
76</td>
77<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p47961338195617"><a name="p47961338195617"></a><a name="p47961338195617"></a>Throws exceptions.</p>
78</td>
79</tr>
80<tr id="row778417510579"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1878575185715"><a name="p1878575185715"></a><a name="p1878575185715"></a>Object lifecycle</p>
81</td>
82<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p1178565175711"><a name="p1178565175711"></a><a name="p1178565175711"></a>Manages NAPI object lifecycle within limited scopes.</p>
83</td>
84</tr>
85<tr id="row83179619572"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1531786125717"><a name="p1531786125717"></a><a name="p1531786125717"></a>JS object</p>
86</td>
87<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p12317663572"><a name="p12317663572"></a><a name="p12317663572"></a>Creates standard object types.</p>
88</td>
89</tr>
90<tr id="row63859616579"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p438696165720"><a name="p438696165720"></a><a name="p438696165720"></a>C-to-NAPI</p>
91</td>
92<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p14386462570"><a name="p14386462570"></a><a name="p14386462570"></a>Converts data types from C to NAPI.</p>
93</td>
94</tr>
95<tr id="row1145119612578"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p13451116115716"><a name="p13451116115716"></a><a name="p13451116115716"></a>NAPI-to-C</p>
96</td>
97<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p12451464574"><a name="p12451464574"></a><a name="p12451464574"></a>Converts data types from NAPI to C.</p>
98</td>
99</tr>
100<tr id="row1451436155720"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p155147625713"><a name="p155147625713"></a><a name="p155147625713"></a>Global instance</p>
101</td>
102<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p551466195713"><a name="p551466195713"></a><a name="p551466195713"></a>Obtains global instances.</p>
103</td>
104</tr>
105<tr id="row65815617579"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p458119617577"><a name="p458119617577"></a><a name="p458119617577"></a>JS value</p>
106</td>
107<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p125818625711"><a name="p125818625711"></a><a name="p125818625711"></a>Provides APIs executing <strong id="b18893622126"><a name="b18893622126"></a><a name="b18893622126"></a>===</strong>, <strong id="b5190121451212"><a name="b5190121451212"></a><a name="b5190121451212"></a>typeof</strong>, <strong id="b01299162121"><a name="b01299162121"></a><a name="b01299162121"></a>instanceof</strong>, and other operations alike.</p>
108</td>
109</tr>
110<tr id="row10649166145711"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p18649196195716"><a name="p18649196195716"></a><a name="p18649196195716"></a>JS object property</p>
111</td>
112<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p164919615574"><a name="p164919615574"></a><a name="p164919615574"></a>Provides functions for performing operations on object properties.</p>
113</td>
114</tr>
115<tr id="row0714260574"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p37143675714"><a name="p37143675714"></a><a name="p37143675714"></a>JS function</p>
116</td>
117<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p771466115711"><a name="p771466115711"></a><a name="p771466115711"></a>Invokes functions and creates instances.</p>
118</td>
119</tr>
120<tr id="row1578176155717"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1782126155711"><a name="p1782126155711"></a><a name="p1782126155711"></a>Object encapsulation</p>
121</td>
122<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p87821967572"><a name="p87821967572"></a><a name="p87821967572"></a>Binds the external context of JS objects.</p>
123</td>
124</tr>
125<tr id="row8854116105717"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1685414619578"><a name="p1685414619578"></a><a name="p1685414619578"></a>Simple asynchronization</p>
126</td>
127<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p1685411612574"><a name="p1685411612574"></a><a name="p1685411612574"></a>Creates asynchronous tasks.</p>
128</td>
129</tr>
130<tr id="row109154635718"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p391556195720"><a name="p391556195720"></a><a name="p391556195720"></a>Promise</p>
131</td>
132<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p1091566135717"><a name="p1091566135717"></a><a name="p1091566135717"></a>Creates a function set for a promise.</p>
133</td>
134</tr>
135<tr id="row1671493313016"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1971512331709"><a name="p1971512331709"></a><a name="p1971512331709"></a>Script</p>
136</td>
137<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p371517332013"><a name="p371517332013"></a><a name="p371517332013"></a>Runs JS code.</p>
138</td>
139</tr>
140</tbody>
141</table>
142
143## How to Develop<a name="section937267212"></a>
144
145The following example describes how to use NAPI to develop a JS API for obtaining the application bundle name.
146
147The prototype of the JS API is as follows:
148
149```
150function getAppName(): string;
151```
152
153The implementation code of the JS API is as follows:
154
155```
156// app.cpp
157#include <stdio.h>
158#include <string.h>
159#include "napi/native_api.h"
160#include "napi/native_node_api.h"
161
162struct AsyncCallbackInfo {
163    napi_env env;
164    napi_async_work asyncWork;
165    napi_deferred deferred;
166};
167
168// C/C++ function corresponding to getAppName()
169napi_value JSGetAppName(napi_env env, napi_callback_info info) {
170    napi_deferred deferred;
171    napi_value promise;
172    // Create a promise.
173    NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
174
175    AsyncCallbackInfo* asyncCallbackInfo = new AsyncCallbackInfo {
176        .env = env,
177        .asyncWork = nullptr,
178        .deferred = deferred,
179    };
180
181    napi_value resourceName;
182    napi_create_string_latin1(env, "GetAppName", NAPI_AUTO_LENGTH, &resourceName);
183    // Create a queue of asynchronous tasks.
184    napi_create_async_work(
185        env, nullptr, resourceName,
186        // Callback for an asynchronous task
187        [](napi_env env, void* data) {},
188        // Callback after the asynchronous task is complete
189        [](napi_env env, napi_status status, void* data) {
190            AsyncCallbackInfo* asyncCallbackInfo = (AsyncCallbackInfo*)data;
191            napi_value appName;
192            const char* str = "com.example.helloworld";
193            napi_create_string_utf8(env, str, strlen(str), &appName);
194            // Trigger the callback.
195            napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, appName);
196            napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
197            delete asyncCallbackInfo;
198        },
199        (void*)asyncCallbackInfo, &asyncCallbackInfo->asyncWork);
200    napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
201    return promise;
202}
203
204// Export the module.
205static napi_value AppExport(napi_env env, napi_value exports)
206{
207    static napi_property_descriptor desc[] = {
208        DECLARE_NAPI_FUNCTION("getAppName", JSGetAppName),
209    };
210    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
211    return exports;
212}
213
214// App module description
215static napi_module appModule = {
216    .nm_version = 1,
217    .nm_flags = 0,
218    .nm_filename = nullptr,
219    .nm_register_func = AppExport,
220    .nm_modname = "app",
221    .nm_priv = ((void*)0),
222    .reserved = {0}
223};
224
225// Register the module.
226extern "C" __attribute__((constructor)) void AppRegister()
227{
228    napi_module_register(&appModule);
229}
230```
231
232The build script is as follows:
233
234```
235// BUILD.gn
236import("//build/ohos.gni")
237ohos_shared_library("app") {
238  # Specify the source file to build.
239  sources = [
240    "app.cpp",
241  ]
242  # Specify build dependencies.
243  deps = [ "//foundation/arkui/napi:ace_napi" ]
244  # Specify the directory where the library is generated.
245  relative_install_dir = "module"
246  subsystem_name = "arkui"
247  part_name = "napi"
248}
249```
250
251Test code to run in your app is as follows:
252
253```
254import app from '@ohos.app'
255export default {
256  testGetAppName() {
257    app.getAppName().then(function (data) {
258      console.info('app name: ' + data);
259    });
260  }
261}
262```
263
264## Repositories Involved<a name="section3970193518214"></a>
265[JS UI framework](https://gitee.com/openharmony/docs/blob/master/en/readme/js-ui-framework.md)
266
267[arkui\_ace\_engine](https://gitee.com/openharmony/arkui_ace_engine/blob/master/README.md)
268
269[arkui\_ace\_engine\_lite](https://gitee.com/openharmony/arkui_ace_engine_lite/blob/master/README.md)
270
271**arkui\_napi**
272
273

README_zh.md

1# NAPI组件<a name="ZH-CN_TOPIC_0000001149901711"></a>
2
3-   [简介](#section11660541593)
4-   [目录](#section161941989596)
5-   [使用场景](#section11759141594811)
6-   [接口说明](#section1611515555510)
7-   [开发步骤](#section937267212)
8-   [相关仓](#section3970193518214)
9
10## 简介<a name="section11660541593"></a>
11
12NAPI(Native API)组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架。
13
14**图 1**  NAPI组件架构图<a name="fig1049423884819"></a>
15
16
17![](figures/zh-cn_image_0000001162437581.jpg)
18
19-   **NativeEngine**
20
21    JS引擎抽象层,统一JS引擎在NAPI层的接口行为。
22
23-   **ModuleManager**
24
25    管理模块,用于模块加载、模块信息缓存。
26
27-   **ScopeManager**
28
29    管理NativeValue的生命周期。
30
31-   **ReferenceManager**
32
33    管理NativeReference的生命周期。
34
35
36## 目录<a name="section161941989596"></a>
37
38NAPI组件源代码在/foundation/arkui/napi下,目录结构如下图所示:
39
40```
41foundation/arkui/napi
42   ├── interfaces
43   │   └── kits
44   │       └── napi           # NAPI头文件目录
45   ├── module_manager         # 模块管理
46   ├── native_engine          # NativeEngine抽象层
47   │   └── impl
48   │       └── ark            # 基于Ark的NativeEngine实现
49   ├── scope_manager          # 作用域管理
50   └── test                   # 测试目录
51```
52
53## 使用场景<a name="section11759141594811"></a>
54
55NAPI适合封装IO、CPU密集型、OS底层等能力并对外暴露JS接口,通过NAPI可以实现JS与C/C++代码互相访问。我们可以通过NAPI接口构建例如网络通信、串口访问、多媒体解码、传感器数据收集等模块。
56
57## 接口说明<a name="section1611515555510"></a>
58
59接口实现详见:**foundation/arkui/napi**。
60
61**表 1**  NAPI接口说明
62
63<a name="table10789351555"></a>
64<table><thead align="left"><tr id="row1878635175515"><th class="cellrowborder" valign="top" width="19.439999999999998%" id="mcps1.2.3.1.1"><p id="p27816352556"><a name="p27816352556"></a><a name="p27816352556"></a>接口分类</p>
65</th>
66<th class="cellrowborder" valign="top" width="80.56%" id="mcps1.2.3.1.2"><p id="p078835105514"><a name="p078835105514"></a><a name="p078835105514"></a>描述</p>
67</th>
68</tr>
69</thead>
70<tbody><tr id="row17863535520"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p678143512552"><a name="p678143512552"></a><a name="p678143512552"></a>模块注册</p>
71</td>
72<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p4781035185515"><a name="p4781035185515"></a><a name="p4781035185515"></a>向模块管理注册模块信息的接口。</p>
73</td>
74</tr>
75<tr id="row67951538205618"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p127961438195616"><a name="p127961438195616"></a><a name="p127961438195616"></a>异常&amp;错误处理</p>
76</td>
77<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p47961338195617"><a name="p47961338195617"></a><a name="p47961338195617"></a>向JS抛出异常。</p>
78</td>
79</tr>
80<tr id="row778417510579"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1878575185715"><a name="p1878575185715"></a><a name="p1878575185715"></a>对象生命周期管理</p>
81</td>
82<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p1178565175711"><a name="p1178565175711"></a><a name="p1178565175711"></a>作用域管理,用于限定某个作用域范围内的NAPI对象的生命周期。</p>
83</td>
84</tr>
85<tr id="row83179619572"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1531786125717"><a name="p1531786125717"></a><a name="p1531786125717"></a>创建JS对象</p>
86</td>
87<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p12317663572"><a name="p12317663572"></a><a name="p12317663572"></a>创建标准的对象类型。</p>
88</td>
89</tr>
90<tr id="row63859616579"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p438696165720"><a name="p438696165720"></a><a name="p438696165720"></a>C类型转NAPI类型</p>
91</td>
92<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p14386462570"><a name="p14386462570"></a><a name="p14386462570"></a>C到NAPI的类型转换。</p>
93</td>
94</tr>
95<tr id="row1145119612578"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p13451116115716"><a name="p13451116115716"></a><a name="p13451116115716"></a>NAPI类型转C类型</p>
96</td>
97<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p12451464574"><a name="p12451464574"></a><a name="p12451464574"></a>NAPI到C的类型转换。</p>
98</td>
99</tr>
100<tr id="row1451436155720"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p155147625713"><a name="p155147625713"></a><a name="p155147625713"></a>获取全局实例的函数</p>
101</td>
102<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p551466195713"><a name="p551466195713"></a><a name="p551466195713"></a>获取全局实例。</p>
103</td>
104</tr>
105<tr id="row65815617579"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p458119617577"><a name="p458119617577"></a><a name="p458119617577"></a>JS值的操作</p>
106</td>
107<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p125818625711"><a name="p125818625711"></a><a name="p125818625711"></a>===、typeof、instanceof等操作符的NAPI接口。</p>
108</td>
109</tr>
110<tr id="row10649166145711"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p18649196195716"><a name="p18649196195716"></a><a name="p18649196195716"></a>JS对象的属性操作</p>
111</td>
112<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p164919615574"><a name="p164919615574"></a><a name="p164919615574"></a>操作对象属性函数集。</p>
113</td>
114</tr>
115<tr id="row0714260574"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p37143675714"><a name="p37143675714"></a><a name="p37143675714"></a>JS函数的操作</p>
116</td>
117<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p771466115711"><a name="p771466115711"></a><a name="p771466115711"></a>方法调用、实例创建。</p>
118</td>
119</tr>
120<tr id="row1578176155717"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1782126155711"><a name="p1782126155711"></a><a name="p1782126155711"></a>对象封装</p>
121</td>
122<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p87821967572"><a name="p87821967572"></a><a name="p87821967572"></a>绑定JS对象的外部上下文关系。</p>
123</td>
124</tr>
125<tr id="row8854116105717"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1685414619578"><a name="p1685414619578"></a><a name="p1685414619578"></a>简单异步</p>
126</td>
127<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p1685411612574"><a name="p1685411612574"></a><a name="p1685411612574"></a>创建异步任务。</p>
128</td>
129</tr>
130<tr id="row109154635718"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p391556195720"><a name="p391556195720"></a><a name="p391556195720"></a>promise</p>
131</td>
132<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p1091566135717"><a name="p1091566135717"></a><a name="p1091566135717"></a>创建promise对象的函数集。</p>
133</td>
134</tr>
135<tr id="row1671493313016"><td class="cellrowborder" valign="top" width="19.439999999999998%" headers="mcps1.2.3.1.1 "><p id="p1971512331709"><a name="p1971512331709"></a><a name="p1971512331709"></a>脚本运行</p>
136</td>
137<td class="cellrowborder" valign="top" width="80.56%" headers="mcps1.2.3.1.2 "><p id="p371517332013"><a name="p371517332013"></a><a name="p371517332013"></a>运行JS代码。</p>
138</td>
139</tr>
140</tbody>
141</table>
142
143## 开发步骤<a name="section937267212"></a>
144
145下面以开发一个获取应用包名的JS接口为例介绍如何使用NAPI。
146
147我们要实现的JS接口原型是:
148
149```
150function getAppName(): string;
151```
152
153以下是实现源码:
154
155```
156// app.cpp
157#include <stdio.h>
158#include <string.h>
159#include "napi/native_api.h"
160#include "napi/native_node_api.h"
161
162struct AsyncCallbackInfo {
163    napi_env env;
164    napi_async_work asyncWork;
165    napi_deferred deferred;
166};
167
168// getAppName对应的C/C++实现函数
169napi_value JSGetAppName(napi_env env, napi_callback_info info) {
170    napi_deferred deferred;
171    napi_value promise;
172    // 创建promise
173    NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
174
175    AsyncCallbackInfo* asyncCallbackInfo = new AsyncCallbackInfo {
176        .env = env,
177        .asyncWork = nullptr,
178        .deferred = deferred,
179    };
180
181    napi_value resourceName;
182    napi_create_string_latin1(env, "GetAppName", NAPI_AUTO_LENGTH, &resourceName);
183    // 创建异步任务队列
184    napi_create_async_work(
185        env, nullptr, resourceName,
186        // 异步任务的回调
187        [](napi_env env, void* data) {},
188        // 异步任务结束后的回调
189        [](napi_env env, napi_status status, void* data) {
190            AsyncCallbackInfo* asyncCallbackInfo = (AsyncCallbackInfo*)data;
191            napi_value appName;
192            const char* str = "com.example.helloworld";
193            napi_create_string_utf8(env, str, strlen(str), &appName);
194            // 触发回调
195            napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, appName);
196            napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
197            delete asyncCallbackInfo;
198        },
199        (void*)asyncCallbackInfo, &asyncCallbackInfo->asyncWork);
200    napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
201    return promise;
202}
203
204// 模块导出入口函数
205static napi_value AppExport(napi_env env, napi_value exports)
206{
207    static napi_property_descriptor desc[] = {
208        DECLARE_NAPI_FUNCTION("getAppName", JSGetAppName),
209    };
210    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
211    return exports;
212}
213
214// app模块描述
215static napi_module appModule = {
216    .nm_version = 1,
217    .nm_flags = 0,
218    .nm_filename = nullptr,
219    .nm_register_func = AppExport,
220    .nm_modname = "app",
221    .nm_priv = ((void*)0),
222    .reserved = {0}
223};
224
225// 注册模块
226extern "C" __attribute__((constructor)) void AppRegister()
227{
228    napi_module_register(&appModule);
229}
230```
231
232对应编译脚本的实现:
233
234```
235// BUILD.gn
236import("//build/ohos.gni")
237ohos_shared_library("app") {
238  # 指定编译源文件
239  sources = [
240    "app.cpp",
241  ]
242  # 指定编译依赖
243  deps = [ "//foundation/arkui/napi:ace_napi" ]
244  # 指定库生成的路径
245  relative_install_dir = "module"
246  subsystem_name = "arkui"
247  part_name = "napi"
248}
249```
250
251应用中的JS测试代码:
252
253```
254import app from '@ohos.app'
255export default {
256  testGetAppName() {
257    app.getAppName().then(function (data) {
258      console.info('app name: ' + data);
259    });
260  }
261}
262```
263
264## 相关仓<a name="section3970193518214"></a>
265[ArkUI框架子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/ArkUI%E6%A1%86%E6%9E%B6%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
266
267[arkui\_ace\_engine](https://gitee.com/openharmony/arkui_ace_engine)
268
269[arkui\_ace\_engine\_lite](https://gitee.com/openharmony/arkui_ace_engine_lite)
270
271**arkui\_napi**
272
273