Explicación detallada de la aplicación NAPI de Openharmony: conceptos básicos

¿Qué es NAPI?

Una comprensión simple es que en Openharmony, es un marco que implementa la interacción entre la aplicación js o ets superior y el C/C++ subyacente.

Explicación oficial en Openharmony: El componente NAPI (API nativa) es un conjunto de marco de desarrollo de extensión de módulo nativo con una interfaz externa desarrollada en base a la especificación N-API de Node.js. También está NAPI, que es adecuado para encapsular IO, CPU intensiva, capa inferior del sistema operativo y otras capacidades y exponer interfaces JS al mundo exterior. A través de NAPI, los códigos JS y C/C++ pueden acceder entre sí. Podemos construir módulos como comunicación de red, acceso a puerto serie, decodificación multimedia y recopilación de datos de sensores a través de la interfaz NAPI.

Ahora, tomando como ejemplo la versión Openharmon V3.1-Release, extraiga el ejemplo de código y divídalo en dos partes para su análisis.

Frente a la interfaz js o ets de nivel superior

1. Definir la interfaz

Los archivos de descripción de la interfaz terminan con el sufijo .d.ts en Openharmony.

En el archivo @ohos.sendfile.d.ts del Servicio de archivos distribuidos (//foundation/filemanagement/dfs_service)

import {AsyncCallback, Callback} from "./basic";

declare namespace SendFile {
  // 异步接口----回调方式
  function sendFile(deviceId: string, sourPath: Array<string>, destPath: Array<string>, fileCount: number, callback: AsyncCallback<number>);
  // 异步接口----Promise方式
  function sendFile(deviceId: string, sourPath: Array<string>, destPath: Array<string>, fileCount: number): Promise<number>;
  // 异步接口----回调方式
  function on(type: 'sendFinished' | 'receiveFinished', callback: AsyncCallback<TransResult>): void;
  // 同步接口
  function off(type: 'sendFinished' | 'receiveFinished'): void;
}

export default SendFile;

Lo anterior proporciona cuatro interfaces JS para desarrolladores de aplicaciones, que se dividen en dos categorías: interfaces sincrónicas e interfaces asincrónicas, y las interfaces asincrónicas se dividen a su vez en métodos de devolución de llamada y Promise.

2. El código JS del desarrollador de la aplicación se puede llamar directamente simplemente importando el módulo.

// 同步调用
import myapp1 from "@ohos.SendFile"
var result = myapp1.off(/* 参数自填*/);

// 异步调用
/** call back 方式的异步调用 */
myapp1.sendFile("xxxx", sourPath, destPath, 4, function (err, ret) {
    ......
});
/** Promise 方式的异步调用 */
var  promiseObj = myapp1.sendFile("xxxx", sourPath, destPath, 4).then(data => {
    ......
}).catch(error => {
    ......
});

3. Notas sobre d.ts

1. Al personalizar el archivo de interfaz d.ts, debe colocar este archivo en el directorio donde se encuentra el SDK de Openharmony en la herramienta de desarrollo de aplicaciones (DevEco Studio), por ejemplo, en la máquina local del autor es D:\Program \Huawei\OpenHarmony3.1 \Sdk\ets\3.1.5.5\api y D:\Program\Huawei\OpenHarmony3.1\Sdk\js\3.1.5.5\api se colocan en diferentes directorios según la persona que llama a la aplicación (js o ets).

2. Openharmony ya tiene un archivo de interfaz d.ts. Según @since 9 mencionado en los comentarios del archivo, no es necesario importar dts por separado después de corresponder a la versión SDK importada correspondiente.

Implementación de interfaz orientada a C++

1. Registro de módulo y mapeo de nombres de métodos.

// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value SendFileExport(napi_env env, napi_value exports)
{
    const char className[] = "SendFile";
    static napi_property_descriptor desc[] = {
        DECLARE_NAPI_FUNCTION("sendFile", JsSendFile),
        DECLARE_NAPI_FUNCTION("on", JsOn),
        DECLARE_NAPI_FUNCTION("off", JsOff),
    };
    napi_value sendFileClass = nullptr;

    napi_define_class(env, className, sizeof(className), JsConstructor, nullptr,
        sizeof(desc) / sizeof(desc[0]), desc, &sendFileClass);

    napi_set_named_property(env, exports, "SendFile", sendFileClass);

    SendFile::RegisterCallback();
    return exports;
}
// 模块注册
NAPI_MODULE(sendfile, SendFileExport)
  • El registro del módulo y la asignación de nombres de métodos se completan mediante las dos macros NAPI_MODULE y DECLARE_NAPI_FUNCTION respectivamente.

  • Aquí dts define dos interfaces sendFile, ¿por qué solo necesita definir y asignar una?

Debido a que el nombre de la interfaz externa de sendFile es el mismo para js o ets, cuando se implementa en C++, js o ets juzgan qué función llamar en función del número o tipo de parámetro pasado.

2. Interfaz de sincronización

Según el mapeo, la implementación C++ correspondiente de la interfaz de sincronización desactivada es JsOff.

  • declaración de función

Cada función asignada debe tener los parámetros napi_env env, napi_callback_info cbinfo y el valor de retorno es napi_value.

// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
......
}

Para implementar llamadas js o ets, el marco NAPI necesita resolver los siguientes problemas: transferencia y conversión de datos

Los parámetros de entrada pasados ​​por js/ets y los resultados devueltos deben convertirse en tipos de datos que puedan ser operados por código C/C++. El marco NAPI introduce un tipo de datos intermedio para corresponder a los js/ets y C de nivel superior. /C++ tipos respectivamente. y los métodos de operación de los tipos de datos.

  • Obtener parámetros de entrada

napi_get_cb_info pasa los parámetros js del parámetro cbinfo. La siguiente es una descripción de la función.

// napi_get_cb_info从napi_callback_info类型的参数中得到回调的参数等数据
napi_status napi_get_cb_info(
  napi_env env,
  napi_callback_info cbinfo, // 传入回调函数的回调信息
  size_t *argc,             // 作为入参传入`argv`数组的大小,并将接收实际的参数个数
  napi_value *argv,         // 存放参数的buffer
  napi_value *this_arg,     // Javascript中的`this`
  void** data               // 接收数据指针
);

argc es el número de parámetros pasados ​​y argv es la matriz de parámetros pasada. En este momento, todos los tipos de parámetros son napi_value.

Obtenga el tipo real del parámetro de entrada mediante el método napi_typeof

// napi_typeof获取指定对象的类型
napi_status napi_typeof(
  napi_env env,
  napi_value value,         // 将要获取类型的Javascript值
  napi_valuetype *result    // Javascript值的类型
);

Según la descripción de d.ts, off solo pasa un parámetro y el tipo de parámetro es una cadena.

// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
    size_t requireArgc = 1;
...
    NAPI_ASSERT(env, argc == requireArgc, "requires 1 parameter"); //参数个数为1 
    napi_valuetype eventValueType = napi_undefined;
	napi_typeof(env, argv[0], &eventValueType);
	NAPI_ASSERT(env, eventValueType == napi_string, "type mismatch for parameter 1");//参数类型为napi_string,即为NAPI中定义一种字符串
...
}
  • Conversión de tipo a un tipo reconocido por C/C++

El método napi_get_value_string_utf8 convierte napi_string a char*

napi_status napi_get_value_string_utf8(napi_env env,
  napi_value value,
  char* buf,
  size_t bufsize,
  size_t* result);
// foundation/filemanagement/dfs_service/frameworks/js/napi/src/sendfile_napi.cpp
napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
...
    char* type = nullptr;
    size_t typeLen = 0;
    napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typeLen);

    NAPI_ASSERT(env, typeLen > 0, "typeLen == 0");
    type = new char[typeLen + 1];

    napi_get_value_string_utf8(env, argv[0], type, typeLen + 1, &typeLen);
...
}
  • valor de retorno

C ++ no tiene valor de retorno y JsOff devolverá nullptr en este momento.

El marco NAPI no tiene nullptr y nullptr se convierte a napi_undefinido a través de napi_get_undefinido.

napi_value JsOff(napi_env env, napi_callback_info cbinfo)
{
...
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    return result;
}

Seguimiento más emocionante

1. Explicación detallada de la aplicación NAPI de Openharmony - capítulo avanzado

Supongo que te gusta

Origin blog.csdn.net/procedurecode/article/details/128740926
Recomendado
Clasificación