In the previous chapter , I mentioned how to use N-API to develop the Node.js Native module, and introduced the napi_create_string_utf8
method to create a UTF-8 encoded string and return it as a return value. In this article, I will continue this topic to introduce the operation of getting the parameters of the native method implemented by C/C++ through N-API by Node.js.
Goals
In this section, we will implement a add
method through N-API that accepts two parameters of type number and returns the sum of the two. add
The implementation of the method is equivalent to the following Javascript code.
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;
}
Method to realize
Parameter is received in the previous chapter, we have already mentioned the use of N-API defined method (napi_env, napi_callback_info)
, which napi_callback_info
is the context information. We can get callback parameters and other data napi_get_cb_info
from the napi_callback_info
type parameters through methods . napi_get_cb_info
The function prototype is as follows:
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 // 接收数据指针
);
It should be noted that if the number of parameters is greater than the requested number argc
, only the argc
number of parameters specified by the copied value will be argv
selected. For example, if the number argc
of requested parameters is set to 0 in the following code , napi_typeof
you will get napi_invalid_arg
an error in subsequent calls because the parameters are not copied to the buffer. If the actual number of parameters is less than the requested number, all parameters will be copied and filled with napi_value
the undefined
value indicated by the type .
After understanding the napi_get_cb_info
method, we can use it to get add
the parameters of the method. For the add
method, two numerical parameters are required, so before calling the napi_get_cb_info
method, we declare the variable of the size_t
type argc
to store the number of parameters we need and to receive the actual number of parameters, and declare an napi_value
array of the type argv
to store the parameters The value of the length is the value of the number of parameters we need.
size_t argc = 2;
napi_value argv[2];
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
After the call napi_get_cb_info
, we also need to verify the parameters. In the above Javascript implementation, we have checked the number of parameters and the types of parameters, let's take a look at how to implement it in N-API.
First, we need to determine the number of parameters actually passed. In the case where the actual number of parameters is less than 2, we need to use the napi_throw_type_error
method to throw an TypeError
error. The code implementation is as follows:
if (argc < 2) {
napi_throw_type_error(env, NULL, "Wrong number of arguments.");
return NULL; // 不再继续执行后续代码
}
napi_throw_type_error
The method will throw a TypeError
type of error. This method is equivalent to using throw new TypeError()
statements. napi_throw_type_error
The function prototype is as follows:
napi_status napi_throw_type_error(
napi_env env,
const char *code, // 可选的错误代码
const char *msg // C语言类型的错误信息字符串
);
Then, we need to verify whether the incoming parameters are of the number
type we need . In N-API, we can napi_typeof
obtain the type of a specified object through a method, and its function prototype is as follows:
napi_status napi_typeof(
napi_env env,
napi_value value, // 将要获取类型的Javascript值
napi_valuetype *result // Javascript值的类型
);
After calling the napi_typeof
method, you can result
get napi_valuetype
the object type represented by its type through its parameters . napi_valuetype
Is an napi_value
enumeration value used to describe the type of stored Javascript object, which is defined as:
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
Corresponding to the standard defined in ECMAScript Boolean
, Null
, Undefined
, Number
, BigInt
, String
, Symbol
and Object
eight kinds of data types, and the corresponding function Function
types. In addition, napi_valuetype
a napi_external
type is also included , which represents an object without any attributes or prototypes.
napi_typeof
typeof
There are also some differences with the operators in Javascript , for example, when the value null
is, the typeof
operator will return object
and napi_typeof
get napi_null
.
For the verification function we need to implement above, we can use the following way to achieve:
napi_valuetype valuetype;
napi_typeof(env, argv[0], &valuetype);
if (valuetype != napi_number) {
// ...
// 处理非数值类型的情况
}
Next, we need to get the value of the parameter and calculate the sum of the two. Because the parameter passed in is a Javascript value type, in order to be able to perform calculations, we need to get the value of the type corresponding to C/C++. N-API is provided that includes napi_get_value_int32
, napi_get_value_double
, napi_get_value_bool
, napi_get_value_string_utf8
etc., a method to obtain values of different types. add
The parameters passed in the method are number
types, and in order to be able to handle floating-point numbers, here we mainly use the napi_get_value_double
method to get the value of the corresponding double
type of the parameter. napi_get_value_double
The function prototype of the method is as follows:
napi_status napi_get_value_double(
napi_env env,
napi_value value, // 获取的Javascript值
double *result // 用于保存对应的double类型值
);
In the above, we have napi_typeof
obtained and verified whether the parameter is a number
type through the method . If it is called directly without verification napi_get_value_double
and the Javascript value is not a number
type, it will return a napi_number_expected
status indicating an error. We can use the following code to achieve double
the operation of obtaining the type value:
double value1, value2;
napi_get_value_double(env, argv[0], &value1);
napi_get_value_double(env, argv[1], &value2);
Finally, we only need to calculate the sum of the two double
types of values, create its corresponding Javascript value and return it. We use double
types for calculations, so we need to use napi_create_double
methods when creating Javascript values . napi_create_double
The corresponding function prototype is as follows:
napi_status napi_create_double(
napi_env env,
double value, // double类型的值
napi_value *result // 保存创建的Javascript值
);
If the calculation of the time instead of converting it to double
the type, N-API also provides napi_create_uint32
, napi_create_int64
, napi_create_bigint_int64
or the like, can select different types according to the specific requirements. In addition, in the previous article, we also mentioned the use of napi_create_string_utf8
creating UTF-8 encoded strings. In addition, N-API as well napi_create_object
, napi_create_array
such as the method used to create the type of object, such as an array, you can go to the N-API documentation in view and select the desired method.
napi_value sum;
napi_create_double(env, value1 + value2, sum);
// return sum;
After completing all the above operations, we only need to follow the completed exports
definition and module registration mentioned in the previous chapter , and then we can use the defined add
method in the js code .
The complete add method code
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;
}
// 模块注册等
Concluding remarks
Similarly, we need to create the binding.gyp
files needed for the build as mentioned in the previous chapter , and run the node-gyp configure build
command to compile. After compiling, import the obtained .node
file in the Javascript code and call the defined add
method:
const {
add } = require('./build/Release/add.node');
console.log(add(1, 2));
// 3
In this article, we introduced how to get the parameters passed from Javascript in C/C++, and get the value of the parameter corresponding to the type in C/C++. In subsequent articles, we will continue to introduce how to call a Javascript method passed by parameters in C/C++, pass parameters to it and receive its return value.