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_utf8
mé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 add
método a través de N-API que acepta dos parámetros de tipo número y devuelve la suma de los dos. add
La 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_info
es la información de contexto. Podemos obtener parámetros de devolución de llamada y otros datos napi_get_cb_info
de los napi_callback_info
parámetros de tipo a través de métodos . napi_get_cb_info
El 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 argc
número de parámetros especificado por el valor copiado argv
. Por ejemplo, si el número argc
de parámetros solicitados se establece en 0 en el siguiente código , napi_typeof
obtendrá napi_invalid_arg
un 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_value
el undefined
valor indicado por el tipo .
Después de comprender el napi_get_cb_info
método, podemos usarlo para obtener add
los parámetros del método. Para el add
método, se requieren dos parámetros de tipo numérico, por lo que antes de llamar al napi_get_cb_info
método, declaramos la variable del size_t
tipo argc
para almacenar la cantidad de parámetros que necesitamos y para recibir la cantidad real de parámetros, y declaramos el napi_value
tipo de matriz argv
a 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_error
método para generar un TypeError
error. 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_error
El método arrojará un TypeError
tipo de error. Este método es equivalente a usar throw new TypeError()
declaraciones. napi_throw_type_error
El 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 number
tipo que necesitamos . En N-API, podemos napi_typeof
obtener 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_typeof
método, puede result
obtener napi_valuetype
el tipo de objeto representado por su tipo a través de sus parámetros . napi_valuetype
Es un napi_value
valor 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_valuetype
En correspondencia con la norma definida en ECMAScript Boolean
, Null
, Undefined
, Number
, BigInt
, String
, Symbol
y Object
ocho tipos de tipos de datos y las correspondientes funciones Function
tipos. Además, napi_valuetype
también se incluye un napi_external
tipo, que representa un objeto sin atributos ni prototipos.
napi_typeof
typeof
También hay algunas diferencias con los operadores en Javascript , por ejemplo, cuando el valor null
es, el typeof
operador devolverá object
y napi_typeof
obtendrá 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_utf8
etc., un método para obtener los valores de diferentes tipos. add
Los parámetros pasados en el método son number
tipos, y para poder manejar números de punto flotante, aquí usamos principalmente el napi_get_value_double
método para obtener el valor del double
tipo correspondiente del parámetro. napi_get_value_double
El 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_typeof
obtenido y verificado si el parámetro es un number
tipo a través del método, si se llama directamente sin verificación napi_get_value_double
y el valor de Javascript no es un number
tipo, devolverá un napi_number_expected
estado indicando un error. Podemos utilizar el siguiente código para lograr double
la 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 double
tipos de valores, crear su correspondiente valor de Javascript y devolverlo. Usamos double
tipos para los cálculos, por lo que necesitamos usar napi_create_double
métodos al crear valores de Javascript . napi_create_double
El 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 double
el tipo, la N-API también proporciona napi_create_uint32
, napi_create_int64
, napi_create_bigint_int64
o 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_utf8
creación de cadenas codificadas en UTF-8. Además, también N-API napi_create_object
, napi_create_array
como 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 exports
definición completa y el registro del módulo mencionado en el capítulo anterior , y luego podemos usar el add
mé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.gyp
archivos necesarios para la compilación como se mencionó en el capítulo anterior y ejecutar el node-gyp configure build
comando para compilar. Después de compilar, importe el .node
archivo obtenido en el código Javascript y llame al add
mé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.