OpenHarmony applications use JavaScript (JS) when calling native APIs. The native APIs (NAPIs) provided by the **arkui_napi** repository are used to implement the interaction with JS. Currently, the **arkui_napi** repository supports some third-party **Node.js** interfaces. The names of the NAPIs are the same as those in the third-party **Node.js**. For details about the interfaces supported, see `libnapi.ndk.json` in this repository.
## How to Develop
The IDE has a default project that uses NAPIs. You can choose `File` > `New` > `Create Project` to create a `Native C++` project. The **cpp** directory is generated in the **main** directory. You can use the NAPIs provided by the **arkui_napi** repository for development.
You can `import` the native .so that contains the JS processing logic. For example, `import hello from 'libhello.so'` to use the **libhello.so** capability. Then, the JS object created using the NAPI can be passed to the `hello` object of the application to call the native capability.
## Development Guidelines
### Registration
* Add **static** to the **nm_register_func** function to prevent symbol conflicts with other .so files.
* The name of the module registration entry, that is, the function decorated by **\_\_attribute\_\_((constructor))**, must be unique.
### .so Naming Rules
Each module has a .so file. For example, if the module name is `hello`, name the .so file **libhello.so**. The `nm_modname` field in `napi_module` must be `hello`, which is the same as the module name. The sample code for importing the .so file is `import hello from 'libhello.so'`.
### JS Objects and Threads
The Ark engine prevents NAPIs from being called to operate JS objects in non-JS threads. Otherwise, the application will crash.
* The NAPIs can be used only in JS threads.
***env** is bound to a thread and cannot be used across threads. The JS object created by a NAPI 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.
### napi_create_async_work
**napi_create_async_work** has two callbacks:
***execute**: processes service logic asynchronously. This callback is not executed by a JS thread; therefore, it cannot call any NAPI. The return value of **execute** is processed by the **complete** callback.
***complete**: calls the NAPI to encapsulate the return value of **execute** into a JS object and return it for processing. This callback is executed by a JS thread.
```c++
napi_statusnapi_create_async_work(napi_envenv,
napi_valueasync_resource,
napi_valueasync_resource_name,
napi_async_execute_callbackexecute,
napi_async_complete_callbackcomplete,
void*data,
napi_async_work*result)
```
## Example 1: Encapsulating Synchronous and Asynchronous APIs for the Storage Module
### Overview
This example shows how to encapsulate the synchronous and asynchronous APIs of the storage module. The storage module implements the functions of storing, obtaining, deleting, and clearing data.
The **getSync** function registered for the storage module is **JSStorageGetSync**. Obtain data from `gKeyValueStorage`, create a string object, and return it.
// Callback 1: This callback contains the service logic to be asynchronously executed and is asynchronously executed by the NAPI. Do not operate JS objects using theNAPI because the execution is asynchronous.
## Example 2: Binding Native and JS Objects for the NetServer Module
### Overview
This example shows how to implement the `on/off/once` method and bind C++ and JS objects using the **wrap** API. The NetServer module implements the network service.
netServer.start(1000);// The port number is 1000. After start is executed, invoke the start callback registered.
}
}
```
## Example 3: Calling Back a JS API in a Non-JS Thread
### Overview
This example describes how to invoke a JS callback in a non-JS thread. For example, a sensor listener is registered for a JS application. The sensor data is reported by an SA. When the SA invokes the client through Inter-Process Communication (IPC), the execution thread is an IPC thread, which is different from the JS thread of the SA. In this case, the JS callback must be thrown to the JS thread to execute. Otherwise, the application will crash.
### Implementation
You can obtain the complete code from `sample/native_module_callback/` in the **arkui_napi** repository.
#### Obtaining the Loop in env and Throwing the Task to the JS Thread
```c++
#include <thread>
#include "napi/native_api.h"
#include "napi/native_node_api.h"
#include "uv.h"
structCallbackContext{
napi_envenv=nullptr;
napi_refcallbackRef=nullptr;
intretData=0;
};
voidcallbackTest(CallbackContext*context)
{
uv_loop_s*loop=nullptr;
// Save the env when the JS callback is registered. Obtain the loop of the JS thread from env.
napi_get_uv_event_loop(context->env,&loop);
// Create uv_work_t to transfer private data (int type 1 in this example). Note that memory must be released after the callback is complete. The logic for generating the returned data is omitted here.
uv_work_t*work=newuv_work_t;
context->retData=1;
work->data=(void*)context;
// Call the libuv API to throw the JS task to the loop for execution.
uv_queue_work(
loop,
work,
// This callback is executed in another common thread to process tasks asynchronously. After the callback is complete, execute the next callback. In this scenario, the callback does not need to execute any task.
[](uv_work_t*work){},
// This callback is executed in the JS thread bound to env.
Describes the surface and touch event held by the ArkUI XComponent, which can be used for the EGL/OpenGLES and media data input and displayed on the ArkUI XComponent.
| id | Indicates the char buffer to keep the ID of this **OH_NativeXComponent** instance. Note that a null-terminator will be appended to the char buffer, so the size of the char buffer should be at least as large as the size of the real id length plus 1. It is recommended that the size of the char buffer be [OH_XCOMPONENT_ID_LEN_MAX + 1]. |
Called when the surface is changed. This API is defined but not implemented in OpenHarmony 3.1 Release. It will be available for use in OpenHarmony 3.1 MR.