




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、NodeJS和C+之间的类型转换虽然在 Node.js 官方网站有很多的关于怎么使用这些 API 的文档,但是在 JavaScript 和 C+ 之间传递数据是一件非常麻烦的事情,C+ 是强类型语言(”1024” 是字符串类型而不是整数类型),而 JavaScript 却总是默认的帮我们做一些类型转换。作者:慎里来源:慎里|2016-12-07 11:23 收藏 分享 我非常喜欢使用 Node.js,但是当涉及到计算密集型的场景时 Node.js 就不能够很好地胜任了。而在这样的情况下 C+ 是一个很好的选择,非常幸运 Node.js 官方提供了C
2、/C+ Addons 的机制让我们能够使用 V8 API 把 Node.js 和 C+ 结合起来。虽然在 Node.js 官方网站有很多的关于怎么使用这些 API 的文档,但是在 JavaScript 和 C+ 之间传递数据是一件非常麻烦的事情,C+ 是强类型语言(”1024” 是字符串类型而不是整数类型),而 JavaScript 却总是默认的帮我们做一些类型转换。JavaScript 的基本类型包括 String,Number,Boolean,null,undefined,V8 使用类继承的方式来定义这类型,这些类型都继承了 Primitive 类,而
3、0;Primitive 继承了 Value,v8 也支持整型(包括 Int32 和 Uint32),而所有的类型定义都可以从 V8 类型文档中看到,除了基本的类型,还有 Object,Array,Map 等类型的定义。基本类型的继承关系如下图:在 V8 中所有 JavaScript 值都是被放在 Local 对象中,通过这个对象指定了 JavaScript 运行时的内存单元。下面这段代定义了一个 Number 类型的值,其中 Test 函数中声明的 isolate 变量代表着 V8 虚拟机中的堆
4、内存,当创建新变量的时候就需要用到它,接下来的一行代码就通过 isolate 声明了一个 Number 类型的变量。1. #include <node.h> 2. #include <v8.h> 3. 4. using namespace v8; 5. 6. void Test(const v8:FunctionCallbackInfo<v8:Value>& args) 7.
5、; Isolate* isolate = args.GetIsolate(); 8. / 声明变量 9. Local<Number> retval = v8:Number:New(isolate, 1000); 10. 11. 12. void init(Local <Object>
6、0;exports, Local<Object> module) 13. NODE_SET_METHOD(exports, "getTestValue", Test); 14. 15. 16. NODE_MODULE(returnValue, init) 看了 V8 类型 API 文档 你会发现对于基本的 JavaScript 类型,只有变量的声明而没有变量的赋值。最初想可能觉得这
7、个非常的奇怪,可是仔细想一想后发现这个是合理的。主要由以下几点原因:· JavaScript 的基本类型是不可变类型,变量都是指向一个不可变的内存单元,var a = 10,则 a 指向的内存单元中包含的值为 5,重新赋值 a = 100,没有改变这个内存单元的值,而是使得 a 指向了另外一个内存单元,其中的值为 100。如果声明两个变量 x,y 的值都为 10,则他们指向的是同一个内存单元。· 函数的传参都是传值,而不是传引用,当在 JavaScript 中调用 C+ 的函数时,如果参数是基本类型则每次都是把这个值拷贝过去,改变参数的值不会影响原来的值。· 使用
8、 Local<Value> 声明基本类型的变量都是对内存单元的引用,因为第一条原因不可能改变引用的值使其指向另外一个内存单元,因此不存在变量的重新赋值。数据流向 C+ -> JavaScript下面 demo 定义了一些常用的 JavaScript 类型,包括基本类型的以及 Object, Array, Fuction。1. #include <node.h> 2. #include <v8.h> 3. 4. using namespace v8; 5
9、. 6. void MyFunction(const v8:FunctionCallbackInfo<Value>& args) 7. Isolate* isolate = args.GetIsolate(); 8. args.GetReturnValue().Set(String:NewFromUtf8(isolate, "Hello World
10、!"); 9. 10. 11. void Test(const v8:FunctionCallbackInfo<v8:Value>& args) 12. Isolate* isolate = args.GetIsolate(); 13. 14. / Number 类型的声明 15.
11、; Local<Number> retval = v8:Number:New(isolate, 1000); 16. 17. / String 类型的声明 18. Local<String> str = v8:String:NewFromUtf8(isolate, "Hello World!")
12、; 19. 20. / Object 类型的声明 21. Local<Object> obj = v8:Object:New(isolate); 22. / 对象的赋值 23. obj->Set(v8:String:NewFromUtf8(isolate, "
13、;arg1"), str); 24. obj->Set(v8:String:NewFromUtf8(isolate, "arg2"), retval); 25. 26. / Function 类型的声明并赋值 27. Local<FunctionTemplate> tpl = v8:F
14、unctionTemplate:New(isolate, MyFunction); 28. Local<Function> fn = tpl->GetFunction(); 29. / 函数名字 30. fn->SetName(String:NewFromUtf8(isolate, "theFunction");
15、0;31. obj->Set(v8:String:NewFromUtf8(isolate, "arg3"), fn); 32. 33. / Boolean 类型的声明 34. Local<Boolean> flag = Boolean:New(isolate, true); 35.
16、 obj->Set(String:NewFromUtf8(isolate, "arg4"), flag); 36. 37. / Array 类型的声明 38. Local<Array> arr = Array:New(isolate); 39. / Array&
17、#160;赋值 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->Se
18、t(3, Number:New(isolate, 1000); 44. obj->Set(String:NewFromUtf8(isolate, "arg5"), arr); 45. 46. / Undefined 类型的声明 47. Local<Value> und = Undefi
19、ned(isolate); 48. obj->Set(String:NewFromUtf8(isolate, "arg6"), und); 49. 50. / null 类型的声明 51. Local<Value> null = Null(isolate); 52.
20、160; obj->Set(String:NewFromUtf8(isolate, "arg7"), null); 53. 54. / 返回给 JavaScript 调用时的返回值 55. args.GetReturnValue().Set(obj); 56. 57. 58. void init(Local <Object&
21、gt; exports, Local<Object> module) 59. NODE_SET_METHOD(exports, "getTestValue", Test); 60. 61. 62. NODE_MODULE(returnValue, init) 所有的 addon 都需要一个初始化的函数,如下面的代码:1. void Initialize(Local<Objec
22、t> exports); 2. NODE_MODULE(module_name, Initialize) Initialize 是初始化的函数,module_name 是编译后产生的二进制文件名,上述代码的模块名为returnValue。上述代码通过 node-gyp 编译后(编译过程官方文档 C/C+ Addons 有详细的介绍),可以通过如下的方式调用。1. / returnValue.node 这个文件就是编译后产生的文件,通过 NODE_MODULE(returnValu
23、e, init) 决定的文件名 2. const returnValue = require('./build/Release/returnValue.node'); 3. console.log(returnValue.getTestValue(); 运行结果如下:数据流向 javaScript -> C+上面的 demo 展示了怎样在在 C+ 定义 JavaScript 类型,数据的是从 C+ 流向 JavaScript,反过来数据也需要从 javaScript 流向 C+,也就是调用 C
24、+ 函数的时候需要传入一些参数。下面的代码展示了参数个数判断,参数类型判断,以及参数类型装换成 V8 类型的过程,包括基本类型以及 Object, Array, Fuction。1. #include <node.h> 2. #include <v8.h> 3. #include <iostream> 4. 5. using namespace v8; 6. using namespace std; 7. 8. vo
25、id GetArgument(const FunctionCallbackInfo<Value>& args) 9. Isolate* isolate = args.GetIsolate(); 10. 11. / 参数长度判断 12. if (args.Length() <
26、2) 13. isolate->ThrowException(Exception:TypeError( 14. String:NewFromUtf8(isolate, "Wrong number of arguments"); 15.
27、160; return; 16. 17. 18. / 参数类型判断 19. if (!args0->IsNumber() | !args1->IsNumber() 20.
28、/抛出错误 21. isolate->ThrowException(Exception:TypeError( 22. String:NewFromUtf8(isolate, "argumnets must be number"); 23.
29、 24. 25. if (!args0->IsObject() 26. printf("I am not Objectn"); 27. 28. 29. if (!args0->
30、IsBoolean() 30. printf("I am not Booleann"); 31. 32. 33. if (!args0->IsArray() 34. p
31、rintf("I am not Arrayn"); 35. 36. 37. if (!args0->IsString() 38. printf("I am not Stringn"); 39.
32、0; 40. 41. if (!args0->IsFunction() 42. printf("I am not Functionn"); 43. 44. 45. if (!args0->
33、IsNull() 46. printf("I am not Nulln"); 47. 48. 49. if (!args0->IsUndefined() 50. pri
34、ntf("I am not Undefinedn"); 51. 52. 53. / js Number 类型转换成 v8 Number 类型 54. Local<Number> value1 = Local<Number>:Cast(args0);
35、 55. Local<Number> value2 = Local<Number>:Cast(args1); 56. double value = value1->NumberValue() + value2->NumberValue(); 57. 58. / js Strin
36、g 类型转换成 v8 String 类型 59. Local<String> str = Local<String>:Cast(args2); 60. String:Utf8Value utfValue(str); 61. cout<<string(*utfValue)<<endl; 6
37、2. 63. / js Array 类型转换成 v8 Array 类型 64. Local<Array> input_array = Local<Array>:Cast(args3); 65. printf("%d, %f %fn", input_array-
38、>Length(), input_array->Get(0)->NumberValue(), input_array->Get(1)->NumberValue(); 66. 67. / js Object 类型转换成 v8 Object 类型 68. Local<Object> obj = Local<Objec
39、t>:Cast(args4); 69. 70. / 根据 key 获取对象中的值 71. Local<Value> a = obj->Get(String:NewFromUtf8(isolate, "a"); 72. Local<Value> b = obj
40、->Get(String:NewFromUtf8(isolate, "b"); 73. 74. / js Array 类型转换成 v8 Array 类型 75. Local<Array> c = Local<Array>:Cast(obj->Get(String:NewFromUtf8(isolate,
41、"c"); 76. cout<<a->NumberValue()<<" "<<b->NumberValue()<<endl; 77. printf("%d, %f %fn", c->Length(), c->Get(0)->NumberValue(), c-&g
42、t;Get(1)->NumberValue(); 78. 79. / js String 类型转换成 v8 String 类型 80. Local<String> cString = Local<String>:Cast(c->Get(2); 81. String:Utf8Value
43、160;utfValueD(cString); 82. cout<<string(*utfValueD)<<endl; 83. 84. / 根据 key 获取对象中的值 85. Local<Object> d = Local<Object>:Cast(obj->Get(String:NewFromU
44、tf8(isolate, "d"); 86. Local<String> dString1 = Local<String>:Cast(d->Get(String:NewFromUtf8(isolate, "m"); 87. String:Utf8Value utfValued1(dString1); 88.
45、; cout<<string(*utfValued1)<<endl; 89. 90. / 根据 key 获取对象中的值 91. Local<String> dString2 = Local<String>:Cast(d->Get(String:NewFromUtf8(isolate, "n"); 92. &
46、#160; String:Utf8Value utfValued2(dString2); 93. cout<<string(*utfValued2)<<endl; 94. 95. / js Booelan 类型转换成 v8 Boolean 类型 96. Local<Boolean> FlagTrue = Local<Boolean>:Cast(args5); 97. cout<<"Flag: "<<FlagTrue->BooleanValue()<<endl;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 申办幼儿园申请书范文2020年
- 商业用电改居民用电申请书范文
- 心理健康指导复习测试有答案
- 高级客户管理员复习试题附答案
- 园洲地皮转让合同范本
- 保山财务咨询合同范本
- 买卖金矿合同范本框架
- 土地测量劳务合同范本
- 和厂家签订合同范本写
- 品牌升级合同范本
- QQ三国副职及日常物品成本计算表v
- 保障农民工工资支付协调机制和工资预防机制
- GB/T 4294-1997氢氧化铝
- 2023年新改版教科版六年级下册科学全册课件
- 2022暖通空调第三版课后题答案
- HUW工法在深基坑围护工程中的应用
- DB37-T 4383-2021 混凝土结构硅烷浸渍技术规程
- 2022年大梦杯福建省初中数学竞赛试题参考答案及评分标准
- 边坡开挖施工要求
- 部编版六年级下册语文教案(全册)
- 2022年湖北成人学士学位英语真题及答案
评论
0/150
提交评论