最近我在著手將一個用C++寫的線路優(yōu)化算法整合進(jìn)node.js服務(wù)端,嘗試了多種方法,包括本地編譯、調(diào)用動態(tài)鏈接庫以及命令行調(diào)用,下面是我的一些心得體會。
利用node-gyp
直接將C++代碼在服務(wù)端中編譯并生成可用的模塊需要用到node-gyp這個庫,具體做法是首先進(jìn)行安裝:
sudo npm install node-gyp -g
為了編譯一個C++文件test.cc
我們需要首先在原來項目中添加如下三個文件:
test.cc
, test.js
和binding.gyp
其中,經(jīng)過測試,binding.gyp
作為配置文件最好放在與項目主入口app.js
同級的目錄下, 三個文件的內(nèi)容分別如下所示,
test.cc:
#include<node.h>
#include<v8.h>
#include<iostream>
using namespace std;
using namespace v8;
void hello(const FunctionCallbackInfo<Value>& args){
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}
void init(Handle<Object>exports){
NODE_SET_METHOD(exports, "hello", hello);
}
NODE_MODULE(test, init);
test.js:
var test = require('build/Release/test');
test.hello('test', function(data){
console.log(data);
});
binding.gyp:
{
"targets":[
{
"target_name":"test",
"sources": [ "./tsModule/test.cc" ]
}
]
}
接下來是配置和編譯的命令:
sudo node-gyp configure
sudo node-gyp build
簡單的分析
我們來觀察一下test.cc中的hello函數(shù),本例中它的作用是返回一個字符串"world",其中第一行代碼Isolate* isolate = args.GetIsolate();
完成了設(shè)定上下文的工作,這個“上下文”在各種v8.h
下的類的聲明中都會用到;第二行設(shè)定了這個函數(shù)作為js模塊的返回值,盡管這個C++函數(shù)本身返回值是void
說到這里,有必要簡單介紹一下v8.h
中定義的用于js與C++交互的幾個數(shù)據(jù)類型,常用的有Value, Object, Array, Number, String等。其中Value是父類,Object對應(yīng)于json格式,剩下三個就是數(shù)組,浮點數(shù)和字符串。比如我們這樣實現(xiàn)hello函數(shù):
void hello(const FunctionCallbackInfo<Value>& args){
Isolate* isolate = args.GetIsolate();
Local<Object>obj = Local<Object>::New(isolate);
obj->Set(String::NewFromUtf8(isolate, "msg"),String::NewFromUtf8(isolate, "nothing"));
args.GetReturnValue().Set(obj);
}
就返回了{msg:'nothing'}
這個json數(shù)據(jù)
在實際使用中,數(shù)組的I/O曾一度讓我非常困擾,后來終于摸到了一些門路,分享如下:
Local<Array>tArr = Local<Array>::Cast(args[0]);
cout<<tArr->Get(0)->NumberValue()<<endl;
以上就是從傳入?yún)?shù)中解析出一個數(shù)組的方法,值得一提的是在C++中調(diào)用標(biāo)準(zhǔn)輸出是可以接到j(luò)s的控制臺中的,方便調(diào)試
更多的API使用方法可以查看官方網(wǎng)站或直接去看v8.h
中的接口源碼