napi系列学习基础篇——NAPI数据类型转换与同步调用

napi的数据类型

通过IDE创建工程的示例代码中,我们使用napi_create_string_utf8函数将C/C++ string转换成NAPI类型——napi_value 。OpenHarmony NAPI将ECMAScript标准中定义的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八种数据类型,以及函数对应的Function类型,统一封装成napi_value类型 (也称为JS类型)。该类型用于接收应用传递过来的数据以及返回数据给应用。 本文将讲述JS类型和C/C++数据类型之间的转换 。

napi的数据类型转换接口

OpenHarmony NAPI提供了很多接口用来napi的数据类型与C/C++数据类型之间的转换。以下列出常用的几种接口

C/C++数据类型转napi类型

  • napi_create_double(napi_env env, double value, napi_value* result);
  • napi_create_int32(napi_env env, int32_t value, napi_value* result);
  • napi_create_uint32(napi_env env, uint32_t value, napi_value* result);
  • napi_create_int64(napi_env env, int64_t value, napi_value* result);
  • napi_create_string_utf8(napi_env env, const char* str, size_t length, napi_value* result);

napi类型转C/C++数据类型

  • napi_get_value_double(napi_env env, napi_value value, double* result);
  • napi_get_value_int32(napi_env env, napi_value value, int32_t* result);
  • napi_get_value_uint32(napi_env env, napi_value value, uint32_t* result);
  • napi_get_value_int64(napi_env env, napi_value value, int64_t* result);
  • napi_get_value_string_utf8(napi_env env, napi_value value, char* buf, size_t bufsize, size_t* result);
  • napi_get_value_bool(napi_env env, napi_value value, bool* result);

同步调用

我们在通过IDE创建工程示例中添加一个简单的接口——add(num1, num2)来讲述具体细节,以及接口同步方式的实现。
NAPI的同步方式调用的扩展API代码处理流程如下图。

添加NAPI扩展API

  • NAPI定义并注册接口
static napi_value add(napi_env env, napi_callback_info info) {
    napi_value reuslt;
    return reuslt;
}
static napi_value registerFunc(napi_env env, napi_value exports)
{
    static napi_property_descriptor desc[] = {
         { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr },
    };
}
  • eTs定义接口
function add(num1: number, num2: number): number;

获取JS参数

NAPI定义API方法时的接收参数为(napi_env, napi_callback_info),其中napi_callback_info为上下文的信息。通过NAPI提供了napi_get_cb_info()方法可从napi_callback_info中获取参数列表、this及其他数据。 napi_get_cb_info函数说明如下:

napi_status napi_get_cb_info(napi_env env,
                             napi_callback_info cbinfo,
                             size_t* argc,
                             napi_value* argv,
                             napi_value* thisArg,
                             void** data)

参数说明:

  • [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可.
  • [in] value: napi_callback_info对象,上下文的信息
  • [in-out] argc: argv数组的长度。若napi_callback_info中实际包含的参数的个数大于请求的数量argc,将只复制argc的值所指定数量的参数只argv中。若实际的参数个数小于请求的数量,将复制全部的参数,数组多余的空间用空值填充,并将参数实际长度写入argc。
  • [out] argv: 用于接收参数列表
  • [out] thisArg: 用于接收this对象
  • [out] data: NAPI的上下文数据 返回值:返回napi_ok表示转换成功,其他值失败。下面的返回napi_status方法一样。

在add方法中,调用napi_get_cb_info函数:

// env、info 参数由NAPI框架传入
static napi_value add(napi_env env, napi_callback_info info) {
  size_t argc = 2;
  napi_value args[2];
  napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
  napi_value reuslt;
  return reuslt;
}

JS类型值转换为C/C++类型的值

因传入的参数是Javascript值类型,并被框架封装成统一的唯一类型——napi_value类型,为了能够进行计算,我们需要获取其对应在C/C++中的类型的值。我们可以用napi类型转C/C++数据类型中的相关接口进行转换。此示例中我们用 napi_get_value_double方式:

static napi_value add(napi_env env, napi_callback_info info) {
  // 获取2个参数,值的类型是js类型(napi_value)
  size_t argc = 2;
  napi_value args[2];
  napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
  // 将js类型(napi_value)的参数值转换成C++类型double
  double value0;
  napi_get_value_double(env, args[0], &value0);
  double value1;
  napi_get_value_double(env, args[1], &value1);
  napi_value reuslt;
  return reuslt;
}

业务逻辑计算

使用Native代码(C/C++代码)完成业务场景逻辑计算。本示例中就简化为2个数字简单相加,代码如下:

static napi_value add(napi_env env, napi_callback_info info) {
  ...
  // 业务逻辑运算
  double sum = value0 + value1;
  ...
}

计算结果转换为JS类型并返回

计算的结果是C/C++ double类型,不能直接返回给JS,需要转换成NAPI node_value类型 。本示例中我们用到 C/C++数据类型转napi类型中的napi_create_double接口:

static napi_value add(napi_env env, napi_callback_info info) {
  ...
  //  将结果由C++类型(double)转换成js类型(napi_value)
  napi_value reuslt;
  napi_create_double(env, sum, &reuslt)
  // 将结果返回到JS
  return result;
}

应用调用

本示例程序也是在DevEco Studio开发,应用调用可参照通过IDE创建工程

import testNapi from "libentry.so"
let num1 = 123
let num2 = 456
let result = testNapi.add(num1, num2)

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

<think>好的,我现在需要帮助用户理解Linux网络子系统中的netif_napi_add函数的功能和用法。用户已经提供了一些相关的引用资料,我需要结合这些资料来构建一个准确的回答。 首先,我要回忆一下NAPI的基本概念。NAPI是Linux网络驱动中用于提高高负载下处理网络数据包效率的一种机制,它结合了中断和轮询的方式。传统的网络驱动在每次数据包到达时都会触发中断,但在高速网络环境下,频繁的中断会导致CPU过载。NAPI通过在有数据到达时禁用中断,改为轮询模式来减少中断次数,从而提高处理效率。 接下来,用户提到的netif_napi_add函数,根据引用[1]中的内容,这个函数的作用是将网络设备NAPI相关联。我需要进一步分析这个函数的具体参数和功能。根据Linux内核代码的常见模式,这个函数可能在初始化网络设备时被调用,用于注册NAPI的结构体和相关的回调函数。 引用[1]提到函数的调用形式是netif_napi_add(netdev, napi, rx_pool, weigh)。这里的参数分别是网络设备结构体、napi结构体、轮询函数和权重。权重可能用于控制每次轮询处理的包数量,防止单个设备占用过多CPU时间。 引用[2]和[3]讨论了NAPI的启用过程,其中napi_enable函数用于设置启用标志,但实际的轮询是在硬中断触发后开始。这说明netif_napi_add可能是在驱动初始化阶段设置好NAPI的相关参数,而实际的启用是在后续的中断处理中进行的。 此外,引用[4]提到了每个CPU的softnet_data结构,这可能NAPI的轮询处理有关,每个CPU核心可能有自己的队列来处理数据包,减少锁竞争。 现在需要将这些信息整合成一个清晰的解释,说明netif_napi_add的作用、参数含义以及它在NAPI机制中的位置。可能还需要提到使用示例,比如在驱动代码中如何调用该函数,并设置正确的权重值。同时,注意事项部分需要强调参数的正确性和初始化的顺序,比如确保napi结构体在使用前正确初始化,以及权重值的合理设置。 最后,根据用户的要求生成相关问题,这些问题应该围绕NAPI的其他函数、性能影响、错误处理等方面展开,帮助用户进一步深入学习。</think>### netif_napi_add 函数功能解析 `netif_napi_add` 是 Linux 网络子系统中用于关联网络设备 NAPI(New API)机制的核心函数,主要功能包括: 1. **注册NAPI实例**:将网络设备(`net_device`) NAPI 结构体(`napi_struct`)绑定,为后续数据包轮询处理提供基础设施[^1]。 2. **设置回调函数**:指定驱动实现的轮询函数(如`rx_pool`),用于在软中断上下文中批量处理网络数据包。 3. **配置权重值**:通过`weigh`参数控制每次轮询的最大处理数据包数量,平衡延迟吞吐量。 函数原型如下: ```c void netif_napi_add(struct net_device *netdev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight); ``` ### 参数详解 | 参数 | 类型 | 作用 | |-----------|---------------------|----------------------------------------------------------------------| | `netdev` | `struct net_device*`| 关联的网络设备指针,如`eth0`对应的设备结构 | | `napi` | `struct napi_struct*`| 驱动分配的NAPI结构体,需通过`netif_napi_del`释放 | | `poll` | 函数指针 | 驱动实现的轮询函数,用于处理接收队列中的数据包 | | `weight` | `int` | 单次轮询最大处理包数,典型值:64(千兆网卡)、256(万兆网卡)[^3] | ### 使用示例(网络驱动片段) ```c struct my_priv { struct napi_struct napi; /* 其他设备私有数据 */ }; static int my_poll(struct napi_struct *napi, int budget) { /* 数据包处理逻辑 */ return processed_packets; } void my_init_module(struct net_device *dev) { struct my_priv *priv = netdev_priv(dev); netif_napi_add(dev, &priv->napi, my_poll, NAPI_POLL_WEIGHT); napi_enable(&priv->napi); // 启用NAPI[^2] } ``` ### 注意事项 1. **初始化顺序**:需在设备注册(`register_netdev`)**前**调用此函数[^1] 2. **内存管理**:`napi_struct` 应内嵌于设备私有数据结构(如`my_priv`)以避免内存泄漏 3. **权重选择**:过高值可能导致CPU占用突增,过低值会降低吞吐量,需实测调优[^3] 4. **并发控制**:轮询函数需正确处理硬中断的同步(如关闭中断的锁机制)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值