参考文章
http://taobaofed.org/blog/2016/09/20/type-casts-between-node-and-cpp/
https://nodejs.org/dist/latest-v8.x/docs/api/addons.html
Addons的机制,允许我们在js和c++互相调用,经常会传递参数或者返回结果,这时候需要做类型转换。包括js -> v8, 和 V8-> js。
1、js -> v8方向
#include <node.h>
#include <v8.h>
#include <iostream>
using namespace v8;
using namespace std;
void GetArguments(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
printf("Hello GetArguments\n");
if (args.Length() == 0) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Wrong number of arguements")));
return;
}
if (!args[0]->IsNumber()) {
printf("I am not Number \n");
return;
}
Local<Number> value1 = Local<Number>::Cast(args[0]);
cout << "first argument = " << value1->NumberValue() << endl;
Local<String> value2 = Local<String>::Cast(args[1]);
String::Utf8Value utfValue(value2);
cout << "second argument = " << string(*utfValue) << endl;
}
void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "getArgs", GetArguments);
}
NODE_MODULE(addon, init)
执行 node-gyp configure build,编译cc文件。
在js文件中测试,
const addon = require('./build/Release/addon-test');
console.log("This should be eight:" + JSON.stringify(addon.getArgs(12, "Hello")));
day
打印为:
Hello GetArguments
first argument = 12
second argument = Hello
可以看到,js中的参数已经传递到了v8的c++代码,并转换成了V8的类型。
2. v8->js方向
#include <node.h>
#include <v8.h>
using namespace v8;
void MyFunction(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Hello MyFunction!"));
}
void TestValue(const v8::FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
printf("Hello TestValue \n");
Local<Object> obj = Object::New(isolate);
// Number type
Local<Number> number = Number::New(isolate, 100);
obj->Set(String::NewFromUtf8(isolate, "numValue"), number);
// String type
Local<String> str = String::NewFromUtf8(isolate, "Hello world!");
obj->Set(String::NewFromUtf8(isolate, "strValue"), str);
// Boolean type
Local<Boolean> flag = Boolean::New(isolate, true);
obj->Set(String::NewFromUtf8(isolate, "boolValue"), flag);
// Array type
Local<Array> array = Array::New(isolate);
array->Set(0, Number::New(isolate, 0));
array->Set(1, Number::New(isolate, 1));
array->Set(2, Number::New(isolate, 2));
array->Set(3, Number::New(isolate, 3));
obj->Set(String::NewFromUtf8(isolate, "arrayValue"), array);
// undefined type
// Local<Value> und = Undefined(isolate);
// obj->Set(String::NewFromUtf8(isolate, "undefinedValue"), und);
// Null type
// Local<Value> null = Null(isolate);
// obj->Set(String::NewFromUtf8(isolate, "nullValue"), null);
// Function type
// Local<FunctionTemplate> ft = FunctionTemplate::New(isolate, MyFunction);
// Local<Function> fn = ft->GetFunction();
// fn->SetName(String::NewFromUtf8(isolate, "myFunction"));
args.GetReturnValue().Set(obj);
}
void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "getTestValue", TestValue);
}
NODE_MODULE(add, init);
js测试代码:
const addon = require('./build/Release/addon-test');
console.log("This should be eight:" + JSON.stringify(addon.getTestValue()));
生成结果为:
Hello TestValue
This should be eight:{"numValue":100,"strValue":"Hello world!","boolValue":true,"arrayValue":[0,1,2,3]}
可以看出,c++中的数据也传到了js层,并对应着不同的类型。