Node.js C++擴展實現

jopen 9年前發布 | 13K 次閱讀 Node.js Node.js 開發

因為有了Node.js,JavaScript可以被用于服務端編程。通過各種擴展,Node.js可以變得非常強大。今天分享下怎樣用C++創建Node.js擴展。

參考原文:Making Dynamsoft Barcode SDK an Addon for Node.js

搭建Nodejs開發環境

要構建擴展,需要安裝node-gyp

npm install -g node-gyp

這個庫里面包涵了JavaScript v8引擎所需要的頭文件以及依賴庫。

創建一個C/C++文件dbr.cc以及配置文件binding.gyp。打開配置文件,在里面加入擴展名和源代碼文件:

{
  "targets": [
    {
      "target_name": "dbr",
      "sources": [ "dbr.cc" ]
    }
  ]
}

現在就可以用來構建dbr.node,用于Node.js的動態鏈接庫,相當于DLL。在命令行中輸入:

node-gyp configure install

這行命令干了兩件事,首先生成了Visual Studio的工程文件。然后調用VS的編譯器生成了動態鏈接庫。可以看下生成的文件結構:

build
    / binding.sln
    / dbr.vcxproj
    / dbr.vcxproj.filters
    / config.gypi
    / Release
        / dbr.node
        / dbr.pdb
        / obj

更多內容可以參考官方文檔Node.js addons

把Dynamsoft Barcode SDK封裝成Node.js擴展

接下來我們只需要使用Visual Studio來編寫代碼,構建工程就可以了。因為node-gyp在配置的時候已經把工程文件里的頭文件路徑和依賴庫路徑都加進去了,我們只需要做很小的修改。現在雙擊binding.sln導入工程。添加Dynamsoft Barcode SDK相關的頭文件路徑和庫路徑。最后添加post-build event用于拷貝DLL到生成目錄:

copy "{installation directory}\Dynamsoft\Barcode Reader 2.0 Trial\Redist\C_C++\*.dll" "$(OutDir)"

現在開始編寫C++代碼。和Java,Python類似,在編寫native代碼的時候,需要首先注冊native函數。初始化Barcode解碼接口:

void Init(Handle<Object> exports) {
    NODE_SET_METHOD(exports, "decodeFile", DecodeFile);
}
 
NODE_MODULE(dbr, Init)

接下來我們把獲取的數據轉換成v8數據類型。使用Local<Object>來存儲一個Barcode結果,使用Local<Array>來存儲所有的Local<Object>。最后通過回調函數把結果返回到JavaScript層。

void DecodeFile(const FunctionCallbackInfo<Value>& args) {
 
    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope(isolate);
 
    // convert v8 string to char *
    String::Utf8Value utfStr(args[0]->ToString());
    char *pFileName = *utfStr;
 
    int option_iMaxBarcodesNumPerPage = -1;
    int option_llBarcodeFormat = -1;
 
    pBarcodeResultArray pResults = NULL;
    ReaderOptions option;
    SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);
 
    // decode barcode image file
    int ret = DBR_DecodeFile(
        pFileName,
        &option,
        &pResults
        );
 
    if (ret == DBR_OK){
        int count = pResults->iBarcodeCount;
        pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
        pBarcodeResult tmp = NULL;
 
        // javascript callback function
        Local<Function> cb = Local<Function>::Cast(args[1]);
        const unsigned argc = 1;
 
        // array for storing barcode results
        Local<Array> barcodeResults = Array::New(isolate);
 
        for (int i = 0; i < count; i++)
        {
            tmp = ppBarcodes[i];
 
            Local<Object> result = Object::New(isolate);
            result->Set(String::NewFromUtf8(isolate, "format"), Number::New(isolate, tmp->llFormat));
            result->Set(String::NewFromUtf8(isolate, "value"), String::NewFromUtf8(isolate, tmp->pBarcodeData));
 
            barcodeResults->Set(Number::New(isolate, i), result);
        }
 
        // release memory
        DBR_FreeBarcodeResults(&pResults);
 
        Local<Value> argv[argc] = { barcodeResults };
        cb->Call(isolate->GetCurrentContext()->Global(), argc, argv);
    }
}

文檔可以參考v8.h以及Chrome V8

現在創建一個JavaScript腳本文件測試一下:

var dbr = require('./build/Release/dbr');
var readline = require('readline');
 
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
 
rl.question("Please input a barcode image path: ", function(answer) {
  // e.g. F:\git\Dynamsoft-Barcode-Reader\Images\AllSupportedBarcodeTypes.tif
  dbr.decodeFile(
    answer,
    function(msg){
      var result = null;
      for (index in msg) {
        result = msg[index]
        console.log(result['format']);
        console.log(result['value']);
        console.log("##################");
      }
    }
  );
 
  rl.close();
});

最后通過命令行運行查看結果:

Node.js C++擴展實現

源碼

https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/samples/Node.js

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!