編寫Node原生模組

Gemini發表於2019-05-14

平常我們寫node module的時候,都是直接用javascript去寫,今天我們來學習下如何使用c/c++來寫node模組,用c/c++寫的優勢就在於,你可以呼叫許多系統級的API,如fork,缺點就是它強平臺依賴的,不一定能在所有平臺下去執行。

寫一個node addon一點都不可怕 * 3

我們用到的工具有2個

1.cmake-js 代替node-gyp,使用起來很方便。
2.nodejs原始碼(需要一些標頭檔案和庫)

cmake-js是使用CMake作為工具,構建跨平臺的Makefile,極大方便了Makefile配置的一個js工具。

我們做一個Hello World
效果如

module.exports.hello = function() { return `world`; };

廢話不多,直接上程式碼

// hello.cc
#include <node.h>

namespace demo {    //此處的名稱空間應該和你的模組名一致

using v8::FunctionCallbackInfo;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));   //設定返回值
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "hello", Method);    //註冊函式
}

NODE_MODULE(demo, init)    //註冊模組

}  // namespace demo

比起普通的js程式碼,的確要複雜很多呀~

然後我們寫好CMakeList.txt

cmake_minimum_required(VERSION 3.3)     #設定cmake的版本 
project(hello)                          #設定專案名稱

include_directories(${CMAKE_JS_INC})    #載入由cmake-js提供的環境變數


set(SOURCE_FILES "hello_world.cc")      #設定我們需要編譯的檔案列表

add_library(hello SHARED exports.cpp ${SOURCE_FILES})  #標明我們要編譯成一個lib,使用定義好的檔案

set_target_properties(hello PROPERTIES PREFIX "" SUFFIX ".node") #設定編譯出來的檔名(預設是libxxx.so,這裡改成xxx.node)

好,在這個資料夾下面執行cmake-js,然後只要編譯連結通過,在你的Build/Release下面就會出現hello.node

然後在你的js檔案裡進行測試

var hello = require("hello").hello;
console.log(hello());  //輸出 world

哈,是不是很簡單!
接下去的任務就是好好學習v8相關的API了,在C/C++環境下,要千萬注意記憶體洩露的問題!

歡迎關注我Github 以及 @Gemini

相關文章