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