Addons
擴展插件(Addons)是動態鏈接的共享對象,這些對象提供了使用C/C++類庫的能力。由於涉及了多個類庫導致了這類API目前比較繁雜,主要包括下述幾個主要類庫:
-
V8 JavaScript,C++類庫,作爲JavaScript的接口類,主要用於創建對象、調用方法等功能。大部分功能在頭文件
v8.h
(在node文件夾下的路徑爲deps/v8/include/v8.h
)中有詳細文檔。 -
libuv 基於C的事件循環庫,當需要等待的文件描述符可讀時,等待定時器,或者等到接受信號時,會調用libuv的接口,也可以說,任何I/O操作,都需要調用libuv庫
-
內部Node的庫,可以通過
node::ObjectWrap
來調用Node.js內部的庫。 -
其他的一些類庫同樣可以在deps/ 中找到。
Node已將所有依賴關係靜態地編譯成可執行文件,因此我們在編譯自己的組件時不需要擔心和這些類庫的鏈接問題。
Hello world
讓我們着手編寫一個Addon的小例子,來達到如下模塊同樣的效果:
module.exports.hello = function() { return 'world'; };
首先,我們需要新建一個hello.cc文件
#include <node.h>
#include <v8.h>
using namespace v8;
Handle<Value> Method(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("world"));
}
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("hello"),
FunctionTemplate::New(Method)->GetFunction());
}
NODE_MODULE(hello, init)
請注意:所有的Node Addons 必須通過以下初始化代碼導出
void Initialize (Handle<Object> exports);
NODE_MODULE(module_name, Initialize)
NODE_MODULE 結尾沒有帶上分號,因爲它不是一個函數(詳細可以看node.h
)
module_name 是最終生成的二進制模塊文件名稱
代碼將會被編譯成hello.node,Addon的二進制文件,在這之前,需要創建一個叫binding.gyp的json格式文件來配置node-gyp進行編譯。
{
"targets": [
{
"target_name": "hello",
"sources": [ "hello.cc" ]
}
]
}
執行node-gyp configure
生成合適的當前平臺的工程建設文件。不需要傳統的Makefile
或vcxproj
。
執行node-gyp build
編譯項目,生成.node
文件,編譯生成的目錄在 build/Release/
編譯成功後,可以在node.js項目中進行調用,創建hello.js
文件通過require函數調用剛編譯完的hello.node模塊。
var addon = require('./build/Release/hello');
console.log(addon.hello()); // 'world'