NodeJS和C++之间的类型转换.docx

上传人:b****2 文档编号:1717818 上传时间:2023-05-01 格式:DOCX 页数:13 大小:250.86KB
下载 相关 举报
NodeJS和C++之间的类型转换.docx_第1页
第1页 / 共13页
NodeJS和C++之间的类型转换.docx_第2页
第2页 / 共13页
NodeJS和C++之间的类型转换.docx_第3页
第3页 / 共13页
NodeJS和C++之间的类型转换.docx_第4页
第4页 / 共13页
NodeJS和C++之间的类型转换.docx_第5页
第5页 / 共13页
NodeJS和C++之间的类型转换.docx_第6页
第6页 / 共13页
NodeJS和C++之间的类型转换.docx_第7页
第7页 / 共13页
NodeJS和C++之间的类型转换.docx_第8页
第8页 / 共13页
NodeJS和C++之间的类型转换.docx_第9页
第9页 / 共13页
NodeJS和C++之间的类型转换.docx_第10页
第10页 / 共13页
NodeJS和C++之间的类型转换.docx_第11页
第11页 / 共13页
NodeJS和C++之间的类型转换.docx_第12页
第12页 / 共13页
NodeJS和C++之间的类型转换.docx_第13页
第13页 / 共13页
亲,该文档总共13页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

NodeJS和C++之间的类型转换.docx

《NodeJS和C++之间的类型转换.docx》由会员分享,可在线阅读,更多相关《NodeJS和C++之间的类型转换.docx(13页珍藏版)》请在冰点文库上搜索。

NodeJS和C++之间的类型转换.docx

NodeJS和C++之间的类型转换

NodeJS和C++之间的类型转换

虽然在Node.js官方网站有很多的关于怎么使用这些API的文档,但是在JavaScript和C++之间传递数据是一件非常麻烦的事情,C++是强类型语言(”1024”是字符串类型而不是整数类型),而JavaScript却总是默认的帮我们做一些类型转换。

作者:

慎里来源:

慎里|2016-12-0711:

23

 收藏

  分享

 

我非常喜欢使用Node.js,但是当涉及到计算密集型的场景时Node.js就不能够很好地胜任了。

而在这样的情况下C++是一个很好的选择,非常幸运Node.js官方提供了C/C++Addons 的机制让我们能够使用V8API把Node.js和C++结合起来。

虽然在Node.js官方网站有很多的关于怎么使用这些API的文档,但是在JavaScript和C++之间传递数据是一件非常麻烦的事情,C++是强类型语言(”1024”是字符串类型而不是整数类型),而JavaScript却总是默认的帮我们做一些类型转换。

JavaScript的基本类型包括String,Number,Boolean,null,undefined,V8使用类继承的方式来定义这类型,这些类型都继承了 Primitive 类,而 Primitive 继承了 Value,v8也支持整型(包括 Int32 和 Uint32),而所有的类型定义都可以从V8 类型文档中看到,除了基本的类型,还有Object,Array,Map等类型的定义。

基本类型的继承关系如下图:

在V8中所有JavaScript值都是被放在 Local 对象中,通过这个对象指定了JavaScript运行时的内存单元。

下面这段代定义了一个 Number 类型的值,其中Test函数中声明的isolate变量代表着V8虚拟机中的堆内存,当创建新变量的时候就需要用到它,接下来的一行代码就通过isolate声明了一个 Number 类型的变量。

1.#include  

2.#include  

3. 

4.using namespace v8; 

5. 

6.void Test(const v8:

:

FunctionCallbackInfo

:

Value>& args) { 

7.    Isolate* isolate = args.GetIsolate(); 

8.    // 声明变量 

9.    Local retval = v8:

:

Number:

:

New(isolate, 1000); 

10.} 

11. 

12.void init(Local  exports, Local module) { 

13.    NODE_SET_METHOD(exports, "getTestValue", Test); 

14.} 

15. 

16.NODE_MODULE(returnValue, init) 

看了V8 类型API文档 你会发现对于基本的JavaScript类型,只有变量的声明而没有变量的赋值。

最初想可能觉得这个非常的奇怪,可是仔细想一想后发现这个是合理的。

主要由以下几点原因:

∙JavaScript的基本类型是不可变类型,变量都是指向一个不可变的内存单元,vara=10,则a指向的内存单元中包含的值为5,重新赋值a=100,没有改变这个内存单元的值,而是使得a指向了另外一个内存单元,其中的值为100。

如果声明两个变量x,y的值都为10,则他们指向的是同一个内存单元。

∙函数的传参都是传值,而不是传引用,当在JavaScript中调用C++的函数时,如果参数是基本类型则每次都是把这个值拷贝过去,改变参数的值不会影响原来的值。

∙使用 Local 声明基本类型的变量都是对内存单元的引用,因为第一条原因不可能改变引用的值使其指向另外一个内存单元,因此不存在变量的重新赋值。

数据流向C++->JavaScript

下面demo定义了一些常用的JavaScript类型,包括基本类型的以及Object,Array,Fuction。

1.#include  

2.#include  

3. 

4.using namespace v8; 

5. 

6.void MyFunction(const v8:

:

FunctionCallbackInfo& args) { 

7.    Isolate* isolate = args.GetIsolate(); 

8.    args.GetReturnValue().Set(String:

:

NewFromUtf8(isolate, "Hello World!

")); 

9.} 

10. 

11.void Test(const v8:

:

FunctionCallbackInfo

:

Value>& args) { 

12.    Isolate* isolate = args.GetIsolate(); 

13. 

14.    // Number 类型的声明 

15.    Local retval = v8:

:

Number:

:

New(isolate, 1000); 

16. 

17.    // String 类型的声明 

18.    Local str = v8:

:

String:

:

NewFromUtf8(isolate, "Hello World!

"); 

19. 

20.    // Object 类型的声明 

21.    Local obj = v8:

:

Object:

:

New(isolate); 

22.    // 对象的赋值 

23.    obj->Set(v8:

:

String:

:

NewFromUtf8(isolate, "arg1"), str); 

24.    obj->Set(v8:

:

String:

:

NewFromUtf8(isolate, "arg2"), retval); 

25. 

26.    // Function 类型的声明并赋值 

27.    Local tpl = v8:

:

FunctionTemplate:

:

New(isolate, MyFunction); 

28.    Local fn = tpl->GetFunction(); 

29.    // 函数名字 

30.    fn->SetName(String:

:

NewFromUtf8(isolate, "theFunction")); 

31.    obj->Set(v8:

:

String:

:

NewFromUtf8(isolate, "arg3"), fn); 

32. 

33.    // Boolean 类型的声明 

34.    Local flag = Boolean:

:

New(isolate, true); 

35.    obj->Set(String:

:

NewFromUtf8(isolate, "arg4"), flag); 

36. 

37.    // Array 类型的声明 

38.    Local arr = Array:

:

New(isolate); 

39.    // Array 赋值 

40.    arr->Set(0, Number:

:

New(isolate, 1)); 

41.    arr->Set(1, Number:

:

New(isolate, 10)); 

42.    arr->Set(2, Number:

:

New(isolate, 100)); 

43.    arr->Set(3, Number:

:

New(isolate, 1000)); 

44.    obj->Set(String:

:

NewFromUtf8(isolate, "arg5"), arr); 

45. 

46.    // Undefined 类型的声明 

47.    Local und = Undefined(isolate); 

48.    obj->Set(String:

:

NewFromUtf8(isolate, "arg6"), und); 

49. 

50.    // null 类型的声明 

51.    Local null = Null(isolate); 

52.    obj->Set(String:

:

NewFromUtf8(isolate, "arg7"), null); 

53. 

54.    // 返回给 JavaScript 调用时的返回值 

55.    args.GetReturnValue().Set(obj); 

56.} 

57. 

58.void init(Local  exports, Local module) { 

59.    NODE_SET_METHOD(exports, "getTestValue", Test); 

60.} 

61. 

62.NODE_MODULE(returnValue, init) 

所有的addon都需要一个初始化的函数,如下面的代码:

1.void Initialize(Local exports); 

2.NODE_MODULE(module_name, Initialize) 

Initialize 是初始化的函数,module_name 是编译后产生的二进制文件名,上述代码的模块名为returnValue。

上述代码通过node-gyp编译后(编译过程官方文档 C/C++Addons 有详细的介绍),可以通过如下的方式调用。

1.// returnValue.node 这个文件就是编译后产生的文件,通过 NODE_MODULE(returnValue, init) 决定的文件名 

2.const returnValue = require('./build/Release/returnValue.node'); 

3.console.log(returnValue.getTestValue()); 

运行结果如下:

数据流向javaScript->C++

上面的demo展示了怎样在在C++定义JavaScript类型,数据的是从C++流向JavaScript,反过来数据也需要从javaScript流向C++,也就是调用C++函数的时候需要传入一些参数。

下面的代码展示了参数个数判断,参数类型判断,以及参数类型装换成V8类型的过程,包括基本类型以及Object,Array,Fuction。

1.#include  

2.#include  

3.#include  

4. 

5.using namespace v8; 

6.using namespace std; 

7. 

8.void GetArgument(const FunctionCallbackInfo& args) { 

9.    Isolate* isolate = args.GetIsolate(); 

10. 

11.    // 参数长度判断 

12.    if (args.Length() < 2) { 

13.        isolate->ThrowException(Exception:

:

TypeError( 

14.            String:

:

NewFromUtf8(isolate, "Wrong number of arguments"))); 

15.        return; 

16.    } 

17. 

18.    // 参数类型判断 

19.    if (!

args[0]->IsNumber() || !

args[1]->IsNumber()) { 

20.        //抛出错误 

21.        isolate->ThrowException(Exception:

:

TypeError( 

22.            String:

:

NewFromUtf8(isolate, "argumnets must be number"))); 

23.    } 

24. 

25.    if (!

args[0]->IsObject()) { 

26.        printf("I am not Object\n"); 

27.    } 

28. 

29.    if (!

args[0]->IsBoolean()) { 

30.        printf("I am not Boolean\n"); 

31.    } 

32. 

33.    if (!

args[0]->IsArray()) { 

34.        printf("I am not Array\n"); 

35.    } 

36. 

37.    if (!

args[0]->IsString()) { 

38.        printf("I am not String\n"); 

39.    } 

40. 

41.    if (!

args[0]->IsFunction()) { 

42.        printf("I am not Function\n"); 

43.    } 

44. 

45.    if (!

args[0]->IsNull()) { 

46.        printf("I am not Null\n"); 

47.    } 

48. 

49.    if (!

args[0]->IsUndefined()) { 

50.        printf("I am not Undefined\n"); 

51.    } 

52. 

53.    // js Number 类型转换成 v8 Number 类型 

54.    Local value1 = Local:

:

Cast(args[0]); 

55.    Local value2 = Local:

:

Cast(args[1]); 

56.    double value = value1->NumberValue() + value2->NumberValue(); 

57. 

58.    // js String 类型转换成 v8 String 类型 

59.    Local str = Local:

:

Cast(args[2]); 

60.    String:

:

Utf8Value utfValue(str); 

61.    cout<

62. 

63.    // js Array 类型转换成 v8 Array 类型 

64.    Local input_array = Local:

:

Cast(args[3]); 

65.    printf("%d, %f %f\n", input_array->Length(), input_array->Get(0)->NumberValue(), input_array->Get

(1)->NumberValue()); 

66. 

67.    // js Object 类型转换成 v8 Object 类型 

68.    Local obj = Local:

:

Cast(args[4]); 

69. 

70.    // 根据 key 获取对象中的值 

71.    Local a = obj->Get(String:

:

NewFromUtf8(isolate, "a")); 

72.    Local b = obj->Get(String:

:

NewFromUtf8(isolate, "b")); 

73. 

74.    // js Array 类型转换成 v8 Array 类型 

75.    Local c = Local:

:

Cast(obj->Get(String:

:

NewFromUtf8(isolate, "c"))); 

76.    cout<NumberValue()<<"   "<NumberValue()<

77.    printf("%d, %f %f\n", c->Length(), c->Get(0)->NumberValue(), c->Get

(1)->NumberValue()); 

78. 

79.    // js String 类型转换成 v8 String 类型 

80.    Local cString = Local:

:

Cast(c->Get

(2)); 

81.    String:

:

Utf8Value utfValueD(cString); 

82.    cout<

83. 

84.    // 根据 key 获取对象中的值 

85.    Local d = Local:

:

Cast(obj->Get(String:

:

NewFromUtf8(isolate, "d"))); 

86.    Local dString1 = Local:

:

Cast(d->Get(String:

:

NewFromUtf8(isolate, "m"))); 

87.    String:

:

Utf8Value utfValued1(dString1); 

88.    cout<

89. 

90.    // 根据 key 获取对象中的值 

91.    Local dString2 = Local:

:

Cast(d->Get(String:

:

NewFromUtf8(isolate, "n"))); 

92.    String:

:

Utf8Value utfValued2(dString2); 

93.    cout<

94. 

95.    // js Booelan 类型转换成 v8 Boolean 类型 

96.    Local FlagTrue = Local:

:

Cast(args[5]); 

97.    cout<<"Flag:

 "<BooleanValue()<

98. 

99.    // js Function 类型转换成 v8 Function 类型 

100.    Local cb = Local:

:

Cast(args[8]); 

101.    const unsigned argc = 2; 

102.    Local argv[2]; 

103.    argv[0] = a; 

104.    argv[1] = b; 

105.    cb->Call(Null(isolate), argc, argv); 

106. 

107.    args.GetReturnValue().Set(value); 

108.} 

109. 

110.void Init(Local  exports, Local  module) { 

111.    NODE_SET_METHOD(module, "exports", GetArgument); 

112.} 

113. 

114.NODE_MODULE(argumentss, Init) 

运行结果如下:

关于其他的类型,我这里就就不一一介绍,V8文档里面都有对应的API。

NAN

由于V8的API还没有彻底稳定下来,所以对于不同版本的Node.js类型相关的API会发生变化,而 NAN 帮我们做了封装,在编码的时候不需要关心版本问题,只需要引入相应的头文件即可。

引入头文件后,可以如下使用方式:

v8:

:

Local

:

Primitive>Nan:

:

Undefined()

v8:

:

Local

:

Primitive>Nan:

:

Null()

参考资料

∙TypeconversionsfromJavaScripttoC++inV8

∙nodeaddon

∙v8typesdocumentation

∙node-gyp

∙gypuserdocumentation

∙nan

【编辑推荐】

1.2016年12月编程语言排行榜:

C作为优秀老语言评级不足10%

2.Java程序员:

工作还是游戏该好好衡量一下

3.常见的JavaScript易错知识点整理

4..NETCore首例Office开源跨平台组件(NPOICore)

5.JavaScript中Write和Writeln的区别

6.能用HTML/CSS解决的问题就不要使用JS

7.Python爬虫爬取美剧网站

展开阅读全文
相关搜索
资源标签

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2