• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Using N-APIs in Application Projects
2
3In OpenHarmony, you can use the N-APIs in C APIs to implement interaction between ArkTS/TS/JS and C/C++. The  N-API names are the same as those in the third-party **Node.js**. Currently, OpenHarmony supports some N-APIs. For details about the APIs supported, see [arkui_napi](https://gitee.com/openharmony/arkui_napi/blob/master/libnapi.ndk.json).
4
5## How to Develop
6
7The DevEco Studio provides a default project that uses N-APIs. You can choose **File** > **New** > **Create Project** to create a Native C++ project. After the project is created, the **cpp** directory is generated in the **entry/src/main** directory. You can use the N-APIs to develop C/C++ code (native code).
8
9You can import the native .so file for ArkTS/TS/JS programming. For example, you can **import hello from 'libhello.so'** to use the **libhello.so** capability and pass the ArkTS/TS/JS object named **hello** to the ArkTS/TS/JS APIs of the application. You can use this object to invoke the N-APIs in **cpp**.
10
11## Basic Features
12The N-APIs implement interaction between ArkTS/TS/JS and C/C++. The following provides two **HelloWorld** project examples:
131. Define an N-API method **Add()**, which is called by ArkTS with two numbers passed in. The N-API **Add**() method adds the two numbers and returns the result to ArkTS.
142. Define an N-API method named **NativeCallArkTS**, which is called by ArkTS with an ArkTS function passed in. The **NativeCallArkTS** method invokes this ArkTS function and returns the result to ArkTS.
15
16The following describes:
171. How an ArkTS method invokes a C++ method.
182. How a C++ method invokes an ArkTS method.
19
20The project has the following files:
21- **entry\src\main\cpp\hello.cpp**: contains the N-API logic.
22- **entry\src\main\ets\pages\index.ets**: contains the ArkTS logic.
23- **entry\src\main\cpp\types\libentry\index.d.ts**: contains the declaration of the N-APIs exposed to ArkTS.
24
25The following provides the comments for the files. Other parts in the project are the same as those in the native default project.
26
27```C++
28// entry\src\main\cpp\hello.cpp
29// Include the N-API header file.
30#include "napi/native_api.h"
31
32// N-API method, which has only two input parameters. You do not need to modify them.
33// napi_env is the current running context.
34// napi_callback_info contains related information, including parameters passed from ArkTS.
35static napi_value Add(napi_env env, napi_callback_info info)
36{
37    // Number of parameters to be obtained from ArkTS. napi_value can be regarded as the representation of the ArkTS value in the N-API method.
38    size_t argc = 2;
39    napi_value args[2] = {nullptr};
40
41    // From info(), obtain the parameters passed from ArkTS. In this example, two ArkTS parameters, arg[0] and arg[1], are obtained.
42    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
43
44    // Convert the obtained ArkTS parameters to the type that can be processed by N-API. In this example, the two numbers passed from ArkTS are converted to the double type.
45    double value0;
46    napi_get_value_double(env, args[0], &value0);
47
48    double value1;
49    napi_get_value_double(env, args[1], &value1);
50
51    // N-API service logic, which is adding two numbers in this example.
52    double nativeSum = value0 + value1;
53
54    // Convert the N-API service logic processing result to an ArkTS value and return the value to ArkTS.
55    napi_value sum;
56    napi_create_double(env, nativeSum , &sum);
57    return sum;
58}
59
60static napi_value NativeCallArkTS(napi_env env, napi_callback_info info)
61{
62    // Number of parameters to be obtained from ArkTS. napi_value can be regarded as the representation of the ArkTS value in the N-API method.
63    size_t argc = 1;
64    napi_value args[1] = {nullptr};
65
66    // From info(), obtain the parameters passed from ArkTS. In this example, one ArkTS parameter, arg[0], is obtained.
67    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
68
69    // Create an ArkTS number as the input parameter of the ArkTS function.
70    napi_value argv = nullptr;
71    napi_create_int32(env, 10, &argv);
72
73    napi_value result = nullptr;
74    // Invoke the ArkTS function in the N-API method, save the return value in result, and return result to ArkTS.
75    napi_call_function(env, nullptr, args[0], 1, &argv, &result);
76
77    return result;
78}
79
80EXTERN_C_START
81// Init() hooks native methods, such as Add and NativeCallArkTS, in exports. exports is the ArkTS object obtained after you import the native capabilities.
82static napi_value Init(napi_env env, napi_value exports)
83{
84    // Function description struct. The third parameter "Add" is the N-API method.
85    // The first parameter "add" is the name of the ArkTS method.
86    napi_property_descriptor desc[] = {
87        { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr },
88        { "nativeCallArkTS", nullptr, NativeCallArkTS, nullptr, nullptr, nullptr, napi_default, nullptr },
89    };
90    // Hook the N-API method to the ArkTS object exports.
91    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
92    return exports;
93}
94EXTERN_C_END
95
96// Information about the module that loads the data. Record information such as the Init() function and module name.
97static napi_module demoModule = {
98    .nm_version =1,
99    .nm_flags = 0,
100    .nm_filename = nullptr,
101    .nm_register_func = Init,
102    .nm_modname = "entry",
103    .nm_priv = ((void*)0),
104    .reserved = { 0 },
105};
106
107// When the .so file is opened, the function is automatically called to register the demoModule module.
108extern "C" __attribute__((constructor)) void RegisterHelloModule(void)
109{
110    napi_module_register(&demoModule);
111}
112```
113
114```js
115// entry\src\main\ets\pages\index.ets
116
117import hilog from '@ohos.hilog';
118// Import the native capabilities.
119import entry from 'libentry.so'
120
121@Entry
122@Component
123struct Index {
124
125  build() {
126    Row() {
127      Column() {
128        // The first button calls the add() method, which uses the N-API Add method to add the two numbers.
129        Button('ArkTS call C++')
130          .fontSize(50)
131          .fontWeight(FontWeight.Bold)
132          .onClick(() => {
133            hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
134            hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', entry.add(2, 3));
135          })
136        // The second button calls the nativeCallArkTS() method, which uses the N-API NativeCallArkTS method to execute the ArkTS function.
137        Button('C++ call ArkTS')
138          .fontSize(50)
139          .fontWeight(FontWeight.Bold)
140          .onClick(() => {
141            hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
142            let ret = entry.nativeCallArkTS((value)=>{return value * 2;});
143            hilog.info(0x0000, 'testTag', 'Test NAPI nativeCallArkTS ret = %{public}d', ret);
144          })
145      }
146      .width('100%')
147    }
148    .height('100%')
149  }
150}
151
152```
153
154```js
155// entry\src\main\cpp\types\libentry\index.d.ts
156// Declare the N-APIs exposed to ArkTS.
157export const add: (a: number, b: number) => number;
158export const nativeCallArkTS: (a: object) => number;
159```
160
161## Development Guidelines
162
163### Registration
164
165* To prevent conflicts with symbols in the .so file, add "static" to the function (such as the Init function) corresponding to **nm_register_func**.
166* The entry of module registration, that is, the function name modified by **\_\_attribute\_\_((constructor))** (for example, the **RegisterHelloModule** function), must be unique.
167
168### .so Naming Rules
169
170The .so file names must comply with the following rules:
171
172* Each module has a .so file.
173* The **nm_modname** field in **napi_module** must be the same as the module name. For example, if the module name is **hello**, name the .so file **libhello.so**. The sample code for importing the .so file is **import hello from 'libhello.so'**.
174
175### Constraints on JS Object Threads
176
177The ArkCompiler protects JS object threads. Improper use may cause an application crash. Observe the following rules:
178
179* The N-APIs can be used only by JS threads.
180* **env** is bound to a thread and cannot be used across threads. The JS object created by an N-API can be used only in the thread, in which the object is created, that is, the JS object is bound to the **env** of the thread.
181
182### Header File Import
183
184Import **napi/native_api.h**. Otherwise, an error indicating that the N-API cannot be found will be reported.
185