Node.js C++擴展實現

由於有了Node.js,JavaScript能夠被用於服務端編程。經過各類擴展,Node.js能夠變得很是強大。今天分享下怎樣用C++建立Node.js擴展。javascript

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

搭建Nodejs開發環境

要構建擴展,須要安裝node-gypjava

npm install -g node-gyp

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

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

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

如今就能夠用來構建dbr.node,用於Node.js的動態連接庫,至關於DLL。在命令行中輸入:github

node-gyp configure install

這行命令幹了兩件事,首先生成了Visual Studio的工程文件。而後調用VS的編譯器生成了動態連接庫。能夠看下生成的文件結構:npm

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到生成目錄:api

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();
});

最後經過命令行運行查看結果:

源碼

https://github.com/dynamsoft-dbr/nodejs

相關文章
相關標籤/搜索