聊一下Node.js中NAPI的napi_value
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相关推荐
- 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查
Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...
- node/js 漏洞_6个可用于检查Node.js中漏洞的工具
node/js 漏洞 Vulnerabilities can exist in all products. The larger your software grows, the greater th ...
- node mongoose_如何使用Express,Mongoose和Socket.io在Node.js中构建实时聊天应用程序
node mongoose by Arun Mathew Kurian 通过阿伦·马修·库里安(Arun Mathew Kurian) 如何使用Express,Mongoose和Socket.io在N ...
- node.js中模块_在Node.js中需要模块:您需要知道的一切
node.js中模块 by Samer Buna 通过Samer Buna 在Node.js中需要模块:您需要知道的一切 (Requiring modules in Node.js: Everythi ...
- boa支持https_Boa: 在 Node.js 中使用 Python
Hello,大家好,有一段时间不见了. 这次主要给大家带来一个好东西,它的主要用途就是能让大家在 Node.js 中使用 Python 的接口和函数.可能你看到这里会好奇,会疑惑,会不解,我 Node ...
- 修改js文件需要重启服务器,关于Node.js中频繁修改代码重启服务器的问题
我们可以使用一个第三方命名行工具,nodemon 来帮我们解决频繁修改代码重启服务器问题. nodemon 是一个基于 Node.jsNode.js 开发的第三方命令行工具,我们使用的时候需要独立安装 ...
- 在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 ...
- 如何在node.js中发出HTTP POST请求?
如何在node.js中使用数据发出出站HTTP POST请求? #1楼 如果您使用请求库,这会变得更容易. var request = require('request');request.post( ...
- 如何在Node.js中退出
用于退出的命令是什么? (即终止Node.js进程) #1楼 从命令行, .exit就是你想要的: $ node > .exit $ 它在REPL文档中有记录 . REPL(Read-Eval- ...
最新文章
- 005-SDK框架之LYWSDKCallBackListener.h
- Jquery中正确使用trim方法以及避免遇到坑
- cdt开发java_Eclipse:可以将CDT和Java IDE放在一起
- 汇编语言---计算有符号数算式的值
- 【转】四阶魔方还原1
- Web Service Software Factory
- 仿360加速球。(实现内存释放)
- linux操作系统是什么,操作系统概述
- hcip第一天复习笔记
- 自媒体矩阵mcn是什么怎么做自媒体mcn矩阵运营
- 《Excel视频3》打印
- 攻防世界 Miscellaneous-200
- Day 01-创建 Vue3.0 工程
- 关系型数据库迁移达梦数据库
- mysql如何用jsp代码进行数据库备份_mysql如何用jsp代码进行数据库备份
- 税分类及配置 tax
- 电子邮箱免费申请注册教程,公司企业邮箱怎么开通注册?
- Python 3.10 尝鲜
- [故事]女博士在京辛酸买房记:同学想读博吗?先买个房吧
- 小学生图片_这家水果店不得了!每天几波小学生轮流打卡只是为了……
热门文章
- Linux搭建web网站综合实验
- onedrive php接口,Onedrive不用API,只用共享链接就能做成分享网盘
- 第一个被赋予公明身份的机器人_史上首次 沙特授予“女性”机器人索菲娅公民身份...
- 言语如何成为交互设计的基础
- Java生成条形码图片,并保存在指定路径
- opencv3计算机视觉python百度云_OpenCV3计算机视觉Python语言实现笔记(二)
- CASIA-SURF活体识别数据集免费免积分下载
- Linux驱动设计——硬件基础
- 风哥MySQL数据库视频培训教程大合集(网盘下载.共10套)
- python pandas 数据分析-读取csv excel