Node.js N-API get method parameters

In the previous chapter , I mentioned how to use N-API to develop the Node.js Native module, and introduced the napi_create_string_utf8method 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 addmethod through N-API that accepts two parameters of type number and returns the sum of the two. addThe 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_infois the context information. We can get callback parameters and other data napi_get_cb_infofrom the napi_callback_infotype parameters through methods . napi_get_cb_infoThe 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 argcnumber of parameters specified by the copied value will be argvselected. For example, if the number argcof requested parameters is set to 0 in the following code , napi_typeofyou will get napi_invalid_argan 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_valuethe undefinedvalue indicated by the type .

After understanding the napi_get_cb_infomethod, we can use it to get addthe parameters of the method. For the addmethod, two numerical parameters are required, so before calling the napi_get_cb_infomethod, we declare the variable of the size_ttype argcto store the number of parameters we need and to receive the actual number of parameters, and declare an napi_valuearray of the type argvto 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_errormethod to throw an TypeErrorerror. The code implementation is as follows:

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

napi_throw_type_errorThe method will throw a TypeErrortype of error. This method is equivalent to using throw new TypeError()statements. napi_throw_type_errorThe 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 numbertype we need . In N-API, we can napi_typeofobtain 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_typeofmethod, you can resultget napi_valuetypethe object type represented by its type through its parameters . napi_valuetypeIs an napi_valueenumeration 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_valuetypeCorresponding to the standard defined in ECMAScript Boolean, Null, Undefined, Number, BigInt, String, Symboland Objecteight kinds of data types, and the corresponding function Functiontypes. In addition, napi_valuetypea napi_externaltype is also included , which represents an object without any attributes or prototypes.

napi_typeoftypeofThere are also some differences with the operators in Javascript , for example, when the value nullis, the typeofoperator will return objectand napi_typeofget 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_utf8etc., a method to obtain values of different types. addThe parameters passed in the method are numbertypes, and in order to be able to handle floating-point numbers, here we mainly use the napi_get_value_doublemethod to get the value of the corresponding doubletype of the parameter. napi_get_value_doubleThe 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_typeofobtained and verified whether the parameter is a numbertype through the method . If it is called directly without verification napi_get_value_doubleand the Javascript value is not a numbertype, it will return a napi_number_expectedstatus indicating an error. We can use the following code to achieve doublethe 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 doubletypes of values, create its corresponding Javascript value and return it. We use doubletypes for calculations, so we need to use napi_create_doublemethods when creating Javascript values . napi_create_doubleThe 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 doublethe type, N-API also provides napi_create_uint32, napi_create_int64, napi_create_bigint_int64or 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_utf8creating UTF-8 encoded strings. In addition, N-API as well napi_create_object, napi_create_arraysuch 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 exportsdefinition and module registration mentioned in the previous chapter , and then we can use the defined addmethod 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.gypfiles needed for the build as mentioned in the previous chapter , and run the node-gyp configure buildcommand to compile. After compiling, import the obtained .nodefile in the Javascript code and call the defined addmethod:

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.

Reference

Guess you like

Origin blog.csdn.net/ghosind/article/details/108132910
Recommended