napi_value是NAPI中非常重要的数据结构,定义如下

typedef struct napi_value__* napi_value;

学过c语言的同学应该知道typedef是什么意思,他的作用就是定义类型别名。

typedef int intType;
intType a = 1;

但是我们发现搜遍Node.js的源码都找不到napi_value__定义,那这个定义是什么意思呢?c语言中,允许定义一个没有定义的结构体的指针。所以napi_value其实就是一个一级指针。他不需要类型信息,因为Node.js不会对他进行解引用。比如在c语言中有以下代码

int a = 1;
int *p = &a;
printf("%d", *p);

这是正确的用法,下面我们来改一下

int a = 1;
void *p = &a;
printf("%d", *p);

执行以上代码我们会得到以下错误信息

main.c: In function ‘main’:
main.c:7:14: warning: dereferencing ‘void *’ pointer7 | printf("%d", *p);|              ^~
main.c:7:14: error: invalid use of void expression

因为在c语言中,对指针解引用的时候,需要有类型信息,比如char、int类型,这时候才能知道要读取多少字节的内存数据。所以改成以下代码就可以了。

int a = 1;
void *p = &a;
printf("%d", *(int *)p);

那么Node.js中的这个定义有什么用呢?我们看看他的用法。下面以NAPI中创建一个数组的API为例。

// 创建一个数组,对应js的数组
napi_status napi_create_array(napi_env env, napi_value* result) {*result = v8impl::JsValueFromV8LocalValue(v8::Array::New(env->isolate));return napi_clear_last_error(env);
}

napi_create_array首先通过v8的接口v8::Array::New拿到一个数组对象。然后调用JsValueFromV8LocalValue,我们看看JsValueFromV8LocalValue的定义。

// 把v8类型转成napi类型
inline napi_value JsValueFromV8LocalValue(v8::Local<v8::Value> local) {return reinterpret_cast<napi_value>(*local);
}

我们看到JsValueFromV8LocalValue返回值是napi_value类型,即一个一级指针。他保存了v8创建的对象的地址信息。我们可以先不用深究*local是什么。接着执行了

*result = napi_value变量;

result类型是napi_value*,即二级指针,这样调用方就拿到了v8创建的对象。我们看一下具体的调用代码。

  napi_value ret;napi_create_array(env, &ret);

执行以上代码后,ret就保存了v8对象的信息。那么这样做有什么好处呢?我们继续看一下对ret的使用。

napi_set_element(env, ret, index, vlaue;)

接着看一下napi_set_element。

// 设置key对应的值,key是数字
napi_status napi_set_element(napi_env env,napi_value object,uint32_t index,napi_value value) {v8::Local<v8::Context> context = env->context();v8::Local<v8::Object> obj;// 校验并转成对应的v8类型CHECK_TO_OBJECT(env, context, obj, object);v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);auto set_maybe = obj->Set(context, index, val);return GET_RETURN_STATUS(env);
}

napi_set_element中最主要的是CHECK_TO_OBJECT。

#define CHECK_TO_OBJECT(env, context, result, src) \CHECK_TO_TYPE((env), Object, (context), (result), (src), napi_object_expected)

是一个宏,继续展开

#define CHECK_TO_TYPE(env, type, context, result, src, status)                \do {                                                                        \CHECK_ARG((env), (src));  // 把napi类型转成v8类型,校验是否为空,非空则返回\auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \CHECK_MAYBE_EMPTY((env), maybe, (status));                                \(result) = maybe.ToLocalChecked();                                        \} while (0)

接着看V8LocalValueFromJsValue

// 把napi类型转成v8类型
inline v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v) {v8::Local<v8::Value> local;memcpy(static_cast<void*>(&local), &v, sizeof(v));return local;
}

V8LocalValueFromJsValue把napi_value v的值复制到local中,我们看看Local类的定义。

class Local {T* val_;
}

即把v的值复制到了val_中,后续就可以按照v8的模式去使用了。

分析到这里,就结束了,那么napi_value到底有什么用呢?napi_value其实就是暂存v8对象信息的变量,他的用处就是可以保存任意类型的v8对象,因为不管什么类型的v8对象,他的地址大小是一样的,我们只需要面对napi_value就行,不需要关注v8的对象类型,当我们调用后续接口时只需要传入napi_value,Node.js就会帮我们处理好之后(转换成对应的v8类型)再调用v8的接口,否则用户就需要这样做。

v8::Local<v8::Object> v8value = v8::Object::New(...);
v8::Local<v8::Array> v8value = v8::Array::New(...);

总的来说,napi_value让我们可以不用关注v8的东西。最后看个小例子
例子1

#include <stdio.h>
typedef struct napi_value__* napi_value;
int main()
{int a = 2;int *p = &a;napi_value ptr = (napi_value)p;printf("%d", *(int *)ptr);return 0;
}

例子2

#include <stdio.h>
typedef void* napi_value;
int main()
{int a = 2;int *p = &a;napi_value ptr = (napi_value)p;printf("%d", *(int *)ptr);return 0;
}

我们看到其实使用void *类型也是可以的。

聊一下Node.js中NAPI的napi_value相关推荐

  1. 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查

    Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...

  2. node/js 漏洞_6个可用于检查Node.js中漏洞的工具

    node/js 漏洞 Vulnerabilities can exist in all products. The larger your software grows, the greater th ...

  3. node mongoose_如何使用Express,Mongoose和Socket.io在Node.js中构建实时聊天应用程序

    node mongoose by Arun Mathew Kurian 通过阿伦·马修·库里安(Arun Mathew Kurian) 如何使用Express,Mongoose和Socket.io在N ...

  4. node.js中模块_在Node.js中需要模块:您需要知道的一切

    node.js中模块 by Samer Buna 通过Samer Buna 在Node.js中需要模块:您需要知道的一切 (Requiring modules in Node.js: Everythi ...

  5. boa支持https_Boa: 在 Node.js 中使用 Python

    Hello,大家好,有一段时间不见了. 这次主要给大家带来一个好东西,它的主要用途就是能让大家在 Node.js 中使用 Python 的接口和函数.可能你看到这里会好奇,会疑惑,会不解,我 Node ...

  6. 修改js文件需要重启服务器,关于Node.js中频繁修改代码重启服务器的问题

    我们可以使用一个第三方命名行工具,nodemon 来帮我们解决频繁修改代码重启服务器问题. nodemon 是一个基于 Node.jsNode.js 开发的第三方命令行工具,我们使用的时候需要独立安装 ...

  7. 在node.js中一次读取一行文件?

    本文翻译自:Read a file one line at a time in node.js? I am trying to read a large file one line at a time ...

  8. 如何在node.js中发出HTTP POST请求?

    如何在node.js中使用数据发出出站HTTP POST请求? #1楼 如果您使用请求库,这会变得更容易. var request = require('request');request.post( ...

  9. 如何在Node.js中退出

    用于退出的命令是什么? (即终止Node.js进程) #1楼 从命令行, .exit就是你想要的: $ node > .exit $ 它在REPL文档中有记录 . REPL(Read-Eval- ...

最新文章

  1. 005-SDK框架之LYWSDKCallBackListener.h
  2. Jquery中正确使用trim方法以及避免遇到坑
  3. cdt开发java_Eclipse:可以将CDT和Java IDE放在一起
  4. 汇编语言---计算有符号数算式的值
  5. 【转】四阶魔方还原1
  6. Web Service Software Factory
  7. 仿360加速球。(实现内存释放)
  8. linux操作系统是什么,操作系统概述
  9. hcip第一天复习笔记
  10. 自媒体矩阵mcn是什么怎么做自媒体mcn矩阵运营
  11. 《Excel视频3》打印
  12. 攻防世界 Miscellaneous-200
  13. Day 01-创建 Vue3.0 工程
  14. 关系型数据库迁移达梦数据库
  15. mysql如何用jsp代码进行数据库备份_mysql如何用jsp代码进行数据库备份
  16. 税分类及配置 tax
  17. 电子邮箱免费申请注册教程,公司企业邮箱怎么开通注册?
  18. Python 3.10 尝鲜
  19. [故事]女博士在京辛酸买房记:同学想读博吗?先买个房吧
  20. 小学生图片_这家水果店不得了!每天几波小学生轮流打卡只是为了……

热门文章

  1. Linux搭建web网站综合实验
  2. onedrive php接口,Onedrive不用API,只用共享链接就能做成分享网盘
  3. 第一个被赋予公明身份的机器人_史上首次 沙特授予“女性”机器人索菲娅公民身份...
  4. 言语如何成为交互设计的基础
  5. Java生成条形码图片,并保存在指定路径
  6. opencv3计算机视觉python百度云_OpenCV3计算机视觉Python语言实现笔记(二)
  7. CASIA-SURF活体识别数据集免费免积分下载
  8. Linux驱动设计——硬件基础
  9. 风哥MySQL数据库视频培训教程大合集(网盘下载.共10套)
  10. python pandas 数据分析-读取csv excel