NodeJS和C++之间的类型转换分析.docx
- 文档编号:16574119
- 上传时间:2023-07-14
- 格式:DOCX
- 页数:13
- 大小:250.88KB
NodeJS和C++之间的类型转换分析.docx
《NodeJS和C++之间的类型转换分析.docx》由会员分享,可在线阅读,更多相关《NodeJS和C++之间的类型转换分析.docx(13页珍藏版)》请在冰点文库上搜索。
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 : Number: : New(isolate, 1000); 10.} 11. 12.void init(Local 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 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 : Number: : New(isolate, 1000); 16. 17. // String 类型的声明 18. Local : String: : NewFromUtf8(isolate, "Hello World! "); 19. 20. // Object 类型的声明 21. Local : 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 : FunctionTemplate: : New(isolate, MyFunction); 28. Local 29. // 函数名字 30. fn->SetName(String: : NewFromUtf8(isolate, "theFunction")); 31. obj->Set(v8: : String: : NewFromUtf8(isolate, "arg3"), fn); 32. 33. // Boolean 类型的声明 34. Local : New(isolate, true); 35. obj->Set(String: : NewFromUtf8(isolate, "arg4"), flag); 36. 37. // Array 类型的声明 38. Local : 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 48. obj->Set(String: : NewFromUtf8(isolate, "arg6"), und); 49. 50. // null 类型的声明 51. Local 52. obj->Set(String: : NewFromUtf8(isolate, "arg7"), null); 53. 54. // 返回给 JavaScript 调用时的返回值 55. args.GetReturnValue().Set(obj); 56.} 57. 58.void init(Local 59. NODE_SET_METHOD(exports, "getTestValue", Test); 60.} 61. 62.NODE_MODULE(returnValue, init) 所有的addon都需要一个初始化的函数,如下面的代码: 1.void Initialize(Local 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 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 : Cast(args[0]); 55. Local : Cast(args[1]); 56. double value = value1->NumberValue() + value2->NumberValue(); 57. 58. // js String 类型转换成 v8 String 类型 59. Local : Cast(args[2]); 60. String: : Utf8Value utfValue(str); 61. cout< 62. 63. // js Array 类型转换成 v8 Array 类型 64. 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 : Cast(args[4]); 69. 70. // 根据 key 获取对象中的值 71. Local : NewFromUtf8(isolate, "a")); 72. Local : NewFromUtf8(isolate, "b")); 73. 74. // js Array 类型转换成 v8 Array 类型 75. Local : Cast(obj->Get(String: : NewFromUtf8(isolate, "c"))); 76. cout< 77. printf("%d, %f %f\n", c->Length(), c->Get(0)->NumberValue(), c->Get (1)->NumberValue()); 78. 79. // js String 类型转换成 v8 String 类型 80. Local : Cast(c->Get (2)); 81. String: : Utf8Value utfValueD(cString); 82. cout< 83. 84. // 根据 key 获取对象中的值 85. Local : Cast(obj->Get(String: : NewFromUtf8(isolate, "d"))); 86. Local : Cast(d->Get(String: : NewFromUtf8(isolate, "m"))); 87. String: : Utf8Value utfValued1(dString1); 88. cout< 89. 90. // 根据 key 获取对象中的值 91. Local : Cast(d->Get(String: : NewFromUtf8(isolate, "n"))); 92. String: : Utf8Value utfValued2(dString2); 93. cout< 94. 95. // js Booelan 类型转换成 v8 Boolean 类型 96. Local : Cast(args[5]); 97. cout<<"Flag: "< 98. 99. // js Function 类型转换成 v8 Function 类型 100. Local : Cast(args[8]); 101. const unsigned argc = 2; 102. Local 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 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爬虫爬取美剧网站
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- NodeJS C+ 之间 类型 转换 分析
![提示](https://static.bingdoc.com/images/bang_tan.gif)