登陆帐号 | 注册帐号
当前位置: 主页 >>开发频道 >>大数据应用 >>

NodeJS和C++之间的范例转换

时间:2017-05-19 19:39来源:互联网 作者:SKY 点击:
固然在 Node.js 官方网站有许多的关于怎么行使这些 API 的文档,可是在 JavaScript 和 C++ 之间转达数据是一件很是贫困的工作,C++ 是强范例说话(”1024” 是字

我很是喜好行使 Node.js,可是当涉及到计较麋集型的场景时 Node.js 就不可以或许很好地胜任了。而在这样的环境下 C++ 是一个很好的选择,很是荣幸 Node.js 官方提供了C/C++ Addons 的机制让我们可以或许行使 V8 API 把 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 等范例的界说。

根基范例的担任相关如下图:

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

在 V8 中全部 JavaScript 值都是被放在 Local 工具中,通过这个工具指定了 JavaScript 运行时的内存单位。

下面这段代界说了一个 Number 范例的值,个中 Test 函数中声明的 isolate 变量代表着 V8 假造机中的堆内存,当建设新变量的时辰就必要用到它,接下来的一行代码就通过 isolate 声明白一个 Number 范例的变量。

#include <node.h> 

#include <v8.h> 

 

using namespace v8; 

 

void Test(const v8::FunctionCallbackInfo<v8::Value>& args) { 

    Isolate* isolate = args.GetIsolate(); 

    // 声明变量 

    Local<Number> retval = v8::Number::New(isolate, 1000); 

 

void init(Local <Object> exports, Local<Object> module) { 

    NODE_SET_METHOD(exports, "getTestValue", Test); 

 

NODE_MODULE(returnValue, init) 

看了 V8 范例 API 文档 你会发明对付根基的 JavaScript 范例,只有变量的声明而没有变量的赋值。最初想也许认为这个很是的稀疏,然则细心想一想后发明这个是公道的。首要由以下几点缘故起因:

JavaScript 的根基范例是不行变范例,变量都是指向一个不行变的内存单位,var a = 10,则 a 指向的内存单位中包括的值为 5,从头赋值 a = 100,没有改变这个内存单位的值,而是使得 a 指向了其它一个内存单位,个中的值为 100。假如声明两个变量 x,y 的值都为 10,则他们指向的是统一个内存单位。

函数的传参都是传值,而不是传引用,当在 JavaScript 中挪用 C++ 的函数时,假如参数是根基范例则每次都是把这个值拷贝已往,改变参数的值不会影响原本的值。

行使 Local<Value> 声明根基范例的变量都是对内存单位的引用,由于第一条缘故起因不行能改变引用的值使其指向其它一个内存单位,因此不存在变量的从头赋值。

数据流向 C++ -> JavaScript

下面 demo 界说了一些常用的 JavaScript 范例,包罗根基范例的以及 Object, Array, Fuction。

#include <node.h> 

#include <v8.h> 

 

using namespace v8; 

 

void MyFunction(const v8::FunctionCallbackInfo<Value>& args) { 

    Isolate* isolate = args.GetIsolate(); 

    args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Hello World!")); 

 

void Test(const v8::FunctionCallbackInfo<v8::Value>& args) { 

    Isolate* isolate = args.GetIsolate(); 

 

    // Number 范例的声明 

    Local<Number> retval = v8::Number::New(isolate, 1000); 

 

    // String 范例的声明 

    Local<String> str = v8::String::NewFromUtf8(isolate, "Hello World!"); 

 

    // Object 范例的声明 

    Local<Object> obj = v8::Object::New(isolate); 

    // 工具的赋值 

    obj->Set(v8::String::NewFromUtf8(isolate, "arg1"), str); 

    obj->Set(v8::String::NewFromUtf8(isolate, "arg2"), retval); 

 

    // Function 范例的声明并赋值 

    Local<FunctionTemplate> tpl = v8::FunctionTemplate::New(isolate, MyFunction); 

    Local<Function> fn = tpl->GetFunction(); 

    // 函数名字 

    fn->SetName(String::NewFromUtf8(isolate, "theFunction")); 

    obj->Set(v8::String::NewFromUtf8(isolate, "arg3"), fn); 

 

    // Boolean 范例的声明 

    Local<Boolean> flag = Boolean::New(isolate, true); 

    obj->Set(String::NewFromUtf8(isolate, "arg4"), flag); 

 

    // Array 范例的声明 

    Local<Array> arr = Array::New(isolate); 

    // Array 赋值 

    arr->Set(0, Number::New(isolate, 1)); 

    arr->Set(1, Number::New(isolate, 10)); 

    arr->Set(2, Number::New(isolate, 100)); 

    arr->Set(3, Number::New(isolate, 1000)); 

    obj->Set(String::NewFromUtf8(isolate, "arg5"), arr); 

 

    // Undefined 范例的声明 

    Local<Value> und = Undefined(isolate); 

    obj->Set(String::NewFromUtf8(isolate, "arg6"), und); 

 

    // null 范例的声明 

    Local<Value> null = Null(isolate); 

    obj->Set(String::NewFromUtf8(isolate, "arg7"), null); 

 

    // 返回给 JavaScript 挪用时的返回值 

    args.GetReturnValue().Set(obj); 

 

void init(Local <Object> exports, Local<Object> module) { 

    NODE_SET_METHOD(exports, "getTestValue", Test); 

 

NODE_MODULE(returnValue, init) 

全部的 addon 都必要一个初始化的函数,如下面的代码:

void Initialize(Local<Object> exports); 

NODE_MODULE(module_name, Initialize) 

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

上述代码通过 node-gyp 编译后(编译进程官方文档 C/C++ Addons 有具体的先容),时代站长网,可以通过如下的方法挪用。

// returnValue.node 这个文件就是编译后发生的文件,通过 NODE_MODULE(returnValue, init) 抉择的文件名 

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

console.log(returnValue.getTestValue()); 

运行功效如下:

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

数据流向 javaScript -> C++

上面的 demo 展示了奈何在在 C++ 界说 JavaScript 范例,数据的是从 C++ 流向 JavaScript,反过来数据也必要从 javaScript 流向 C++,也就是挪用 C++ 函数的时辰必要传入一些参数。

下面的代码展示了参数个数判定,参数范例判定,以及参数范例装换成 V8 范例的进程,包罗根基范例以及 Object, Array, Fuction。

#include <node.h> 

#include <v8.h> 

#include <iostream> 

 

using namespace v8; 

using namespace std; 

 

void GetArgument(const FunctionCallbackInfo<Value>& args) { 

    Isolate* isolate = args.GetIsolate(); 

 

    // 参数长度判定 

    if (args.Length() < 2) { 

        isolate->ThrowException(Exception::TypeError( 

(责任编辑:SKY)
织梦二维码生成器
------分隔线----------------------------
栏目列表
推荐内容