Parámetros del método get de Node.js N-API

En el capítulo anterior , mencioné cómo usar N-API para desarrollar el módulo nativo de Node.js e introduje el napi_create_string_utf8método para crear una cadena codificada en UTF-8 y devolverla como valor de retorno. En este artículo, continuaré con este tema para presentar la operación de obtener los parámetros del método nativo implementado por C / C ++ a través de N-API por Node.js.

Metas

En esta sección, implementaremos un addmétodo a través de N-API que acepta dos parámetros de tipo número y devuelve la suma de los dos. addLa implementación del método es equivalente al siguiente código Javascript.

function add(a, b) {
    
    
  if (arguments.length < 2) {
    
    
    throw new TypeError('Wrong number of arguments');
  }

  if (typeof a !== 'number' || typeof b !== 'number') {
    
    
    throw new TypeError('Wrong arguments');
  }

  return a + b;
}

Método para realizar

El parámetro se recibe en el capítulo anterior, ya hemos mencionado el uso del método definido por N-API (napi_env, napi_callback_info), que napi_callback_infoes la información de contexto. Podemos obtener parámetros de devolución de llamada y otros datos napi_get_cb_infode los napi_callback_infoparámetros de tipo a través de métodos . napi_get_cb_infoEl prototipo de función es el siguiente:

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 // 接收数据指针
);

Cabe señalar que si el número de parámetros es mayor que el número solicitado argc, solo se seleccionará el argcnúmero de parámetros especificado por el valor copiado argv. Por ejemplo, si el número argcde parámetros solicitados se establece en 0 en el siguiente código , napi_typeofobtendrá napi_invalid_argun error en las llamadas posteriores porque los parámetros no se copian en el búfer. Si el número real de parámetros es menor que el número solicitado, todos los parámetros se copiarán y completarán con napi_valueel undefinedvalor indicado por el tipo .

Después de comprender el napi_get_cb_infométodo, podemos usarlo para obtener addlos parámetros del método. Para el addmétodo, se requieren dos parámetros de tipo numérico, por lo que antes de llamar al napi_get_cb_infométodo, declaramos la variable del size_ttipo argcpara almacenar la cantidad de parámetros que necesitamos y para recibir la cantidad real de parámetros, y declaramos el napi_valuetipo de matriz argva almacenar. los parámetros El valor de la longitud es el valor del número de parámetros que necesitamos.

size_t argc = 2;
napi_value argv[2];

status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);

Después de la llamada napi_get_cb_info, también necesitamos verificar los parámetros. En la implementación de Javascript anterior, hemos verificado la cantidad de parámetros y los tipos de parámetros, echemos un vistazo a cómo implementarlo en N-API.

Primero, necesitamos determinar el número de parámetros que realmente se pasan. En el caso de que el número real de parámetros sea inferior a 2, debemos utilizar el napi_throw_type_errormétodo para generar un TypeErrorerror. La implementación del código es la siguiente:

if (argc < 2) {
    
    
  napi_throw_type_error(env, NULL, "Wrong number of arguments.");
  return NULL; // 不再继续执行后续代码
}

napi_throw_type_errorEl método arrojará un TypeErrortipo de error. Este método es equivalente a usar throw new TypeError()declaraciones. napi_throw_type_errorEl prototipo de función es el siguiente:

napi_status napi_throw_type_error(
  napi_env env,
  const char *code, // 可选的错误代码
  const char *msg // C语言类型的错误信息字符串
);

Luego, necesitamos verificar si los parámetros entrantes son del numbertipo que necesitamos . En N-API, podemos napi_typeofobtener el tipo de un objeto especificado a través de un método, y su prototipo de función es el siguiente:

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

Después de llamar al napi_typeofmétodo, puede resultobtener napi_valuetypeel tipo de objeto representado por su tipo a través de sus parámetros . napi_valuetypeEs un napi_valuevalor de enumeración que se utiliza para describir el tipo de objeto Javascript almacenado, que se define como:

typedef enum {
    
    
  napi_undefined,
  napi_null,
  napi_boolean,
  napi_number,
  napi_string,
  napi_symbol,
  napi_object,
  napi_function,
  napi_external,
  napi_bigint
} napi_valuetype;

napi_valuetypeEn correspondencia con la norma definida en ECMAScript Boolean, Null, Undefined, Number, BigInt, String, Symboly Objectocho tipos de tipos de datos y las correspondientes funciones Functiontipos. Además, napi_valuetypetambién se incluye un napi_externaltipo, que representa un objeto sin atributos ni prototipos.

napi_typeoftypeofTambién hay algunas diferencias con los operadores en Javascript , por ejemplo, cuando el valor nulles, el typeofoperador devolverá objecty napi_typeofobtendrá napi_null.

Para la función de verificación que necesitamos implementar arriba, podemos usar la siguiente forma para lograr:

napi_valuetype valuetype;

napi_typeof(env, argv[0], &valuetype);

if (valuetype != napi_number) {
    
    
  // ...
  // 处理非数值类型的情况
}

A continuación, necesitamos obtener el valor del parámetro y calcular la suma de los dos. Debido a que el parámetro pasado es un tipo de valor de Javascript, para poder realizar cálculos, necesitamos obtener el valor del tipo correspondiente a C / C ++. Se proporciona N-API que incluye napi_get_value_int32, napi_get_value_double, napi_get_value_bool, napi_get_value_string_utf8etc., un método para obtener los valores de diferentes tipos. addLos parámetros pasados en el método son numbertipos, y para poder manejar números de punto flotante, aquí usamos principalmente el napi_get_value_doublemétodo para obtener el valor del doubletipo correspondiente del parámetro. napi_get_value_doubleEl prototipo de función del método es el siguiente:

napi_status napi_get_value_double(
  napi_env env,
  napi_value value, // 获取的Javascript值
  double *result // 用于保存对应的double类型值
);

En lo anterior hemos napi_typeofobtenido y verificado si el parámetro es un numbertipo a través del método, si se llama directamente sin verificación napi_get_value_doubley el valor de Javascript no es un numbertipo, devolverá un napi_number_expectedestado indicando un error. Podemos utilizar el siguiente código para lograr doublela operación de obtener el valor del tipo:

double value1, value2;

napi_get_value_double(env, argv[0], &value1);
napi_get_value_double(env, argv[1], &value2);

Finalmente, solo necesitamos calcular la suma de los dos doubletipos de valores, crear su correspondiente valor de Javascript y devolverlo. Usamos doubletipos para los cálculos, por lo que necesitamos usar napi_create_doublemétodos al crear valores de Javascript . napi_create_doubleEl prototipo de función correspondiente es el siguiente:

napi_status napi_create_double(
  napi_env env,
  double value, // double类型的值
  napi_value *result // 保存创建的Javascript值
);

Si el cálculo del tiempo en lugar de convertirlo en doubleel tipo, la N-API también proporciona napi_create_uint32, napi_create_int64, napi_create_bigint_int64o similar, puede seleccionar diferentes tipos de acuerdo con los requisitos específicos. Además, en el artículo anterior, también mencionamos el uso de la napi_create_string_utf8creación de cadenas codificadas en UTF-8. Además, también N-API napi_create_object, napi_create_arraycomo el método utilizado para crear el tipo de objeto, como una matriz, puede ir a la documentación de N-API a la vista y seleccionar el método deseado.

napi_value sum;

napi_create_double(env, value1 + value2, sum);

// return sum;

Después de completar todas las operaciones anteriores, solo necesitamos seguir la exportsdefinición completa y el registro del módulo mencionado en el capítulo anterior , y luego podemos usar el addmétodo definido en el código js .

El código completo del método de adición

napi_value add(napi_env env, napi_callback_info info) {
    
    
  napi_status status;

  size_t argc = 2;
  napi_value argv[2];

  status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
  assert(status == napi_ok);

  if (argc < 2) {
    
    
    napi_throw_type_error(env, NULL, "Wrong number of arguments.");
    return NULL;
  }

  napi_valuetype valueType1, valueType2;

  status = napi_typeof(env, argv[0], &valueType1);
  assert(status == napi_ok);

  status = napi_typeof(env, argv[1], &valueType2);
  assert(status == napi_ok);

  if (valueType1 != napi_number || valueType2 != napi_number) {
    
    
    napi_throw_type_error(env, NULL, "Wrong arguments");
    return NULL;
  }

  double value1, value2;

  status = napi_get_value_double(env, argv[0], &value1);
  assert(status == napi_ok);

  status = napi_get_value_double(env, argv[1], &value2);
  assert(status == napi_ok);

  napi_value sum;
  status = napi_create_double(env, value1 + value2, &sum);
  assert(status == napi_ok);

  return sum;
}

// 模块注册等

Observaciones finales

De manera similar, necesitamos crear los binding.gyparchivos necesarios para la compilación como se mencionó en el capítulo anterior y ejecutar el node-gyp configure buildcomando para compilar. Después de compilar, importe el .nodearchivo obtenido en el código Javascript y llame al addmétodo definido :

const {
    
     add } = require('./build/Release/add.node');

console.log(add(1, 2));
// 3

En este artículo, presentamos cómo obtener los parámetros pasados ​​desde Javascript en C / C ++ y obtener el valor del parámetro correspondiente al tipo en C / C ++. En artículos posteriores, continuaremos presentando cómo llamar a un método Javascript pasado por parámetros en C / C ++, pasarle parámetros y recibir su valor de retorno.

Referencia

Supongo que te gusta

Origin blog.csdn.net/ghosind/article/details/108132910
Recomendado
Clasificación