亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Node.js插件的正確編寫方式

2019-11-20 14:18:03
字體:
來源:轉載
供稿:網友

Node.js在利用JavaScript編寫后端方面效果拔群,值得我們多加嘗試。不過如果大家需要一些無法直接使用的功能甚至是根本無從實現的模塊使用,那么能否從C/C++庫當中引入此類成果呢?答案是肯定的,大家要做的就是編寫一款插件,并借此在自己的JavaScript代碼中使用其它代碼庫的資源。下面我們就一同開始今天的探詢之旅。

介紹

正如Node.js在官方說明文檔中所言,插件是以動態方式進行鏈接的共享式對象,能夠將JavaScript代碼與C/C++庫接駁起來。這意味著我們可以引用任何來自C/C++庫中的內容,并通過創建插件的方式將其納入到Node.js當中。

作為實例,我們將為標準std::string對象創建一套封裝。

準備工作

在我們開始編寫工作之前,大家首先需要確保自己已經準備好所有后續模塊編譯所需要的素材。大家需要node-gyp及其全部依賴關系。大家可以利用以下命令安裝node-gyp:

npm install -g node-gyp

 在依賴性方面,我們需要為Unix系統準備以下項目:• Python (要求2.7版本, 3.x無法正常起效)

• make

• 一款C++編譯器工具鏈(例如gpp或者g++)

舉例來說,在Ubuntu上大家可以利用以下命令安裝所有上述項目(其中Python 2.7應該已經預先安裝完畢了):

sudo apt-get install build-essentials 

在Windows系統環境下,大家需要的是:

• Python (2.7.3版本, 3.x無法正常起效)

• 微軟Visual Studio C++ 2010 (適用于Windows XP/Vista)

• 微軟Visual Studio C++ 2012 for Windows Desktop (適用于Windows 7/8)

強調一點,Visual Studio的Express版本也能正常起效。

binding.gyp文件

該文件由node-gyp使用,旨在為我們的插件生成適當的build文件。大家可以點擊此處查看維基百科提供的.gyp文件說明文檔,但今天我們要使用的實例非常簡單、因此只需使用以下代碼即可:

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

其中target_name可以設置為大家喜歡的任何內容。而sources數組當中包含該插件需要用到的所有源文件。在我們的實例中還包括addon.cc,它的作用在于容納編譯插件及stdstring.cc所必需的代碼,外加我們的封裝類。

STDStringWrapper類

第一步,我們要做的是在stdstring.h文件當中定義自己的類。如果大家對于C++編程比較熟悉,那么也一定不會對以下兩行代碼感到陌生。

#ifndef STDSTRING_H #define STDSTRING_H

這屬于標準的include guard。接下來,我們需要將以下兩個header納入include范疇:

#include 
#include
第一個面向的是std::string類,而第二個include則作用于全部與Node以及V8相關的內容。

這一步完成之后,我們可以對自己的類進行聲明:

class STDStringWrapper : public node::ObjectWrap {
對于所有我們打算包含在插件當中的類來說,我們必須擴展node::ObjectWrap類。

現在我們可以開始定義該類的private屬性了:

private:   std::string* s_;     explicit STDStringWrapper(std::string s = "");   ~STDStringWrapper();

除了構造函數與解析函數,我們還需要為std::string定義一個指針。這是該技術的核心所在,能夠被用于將C/C++代碼庫與Node相對接――我們為該C/C++類定義一個私有指針,并將在隨后的所有方法中利用該指針實現操作。

現在我們聲明的constructor靜態屬性,它將為我們在V8中創建的類提供函數:

static v8::Persistent constructor;
感興趣的朋友可以點擊此處參閱模板說明方案以獲取更多細節信息。

現在我們還需要一個New方法,它將被分配給前面提到的constructor,同時V8會對我們的類進行初始化:

static v8::Handle New(const v8::Arguments& args);
 作用于V8的每一個函數都應該遵循以下要求:它將接受指向v8::Arguments對象的引用,并返回一個v8::Handle>v8::Value>――這正是我們在使用強類型C++編碼時,V8處理弱類型JavaScript的一貫方式。

在此之后,我們還需要將另外兩個方法插入到對象的原型當中:

static v8::Handle add(const v8::Arguments& args); static v8::Handle toString(const v8::Arguments& args);

其中toString()方法允許我們在將其與普通JavaScript字符串共同使用時獲得s_的值而非[Object object]的值。

最后,我們將引入初始化方法(此方法將由V8調用并指派給constructor函數)并關閉include guard:

public:     static void Init(v8::Handle exports); };   #endif

其中exports對象在JavaScript模塊中的作用等同于module.exports。

stdstring.cc文件、構造函數與解析函數

現在來創建stdstring.cc文件。我們首先需要include我們的header:

#include "stdstring.h" 

下面為constructor定義屬性(因為它屬于靜態函數):

v8::Persistent STDStringWrapper::constructor; 

這個為類服務的構造函數將分配s_屬性:

STDStringWrapper::STDStringWrapper(std::string s) {   s_ = new std::string(s); }

而解析函數將對其進行delete,從而避免內存溢出:

STDStringWrapper::~STDStringWrapper() {   delete s_; }

再有,大家必須delete掉所有與new一同分配的內容,因為每一次此類情況都有可能造成異常,因此請牢牢記住上述操作或者使用共享指針。

Init方法

該方法將由V8加以調用,旨在對我們的類進行初始化(分配constructor,將我們所有打算在JavaScript當中使用的內容安置在exports對象當中):

void STDStringWrapper::Init(v8::Handle exports) {
首先,我們需要為自己的New方法創建一個函數模板:

v8::Local tpl = v8::FunctionTemplate::New(New);
這有點類似于JavaScipt當中的new Function――它允許我們準備好自己的JavaScript類。

現在我們可以根據實際需要為該函數設定名稱了(如果大家漏掉了這一步,那么構造函數將處于匿名狀態,即名稱為function someName() {}或者function () {}):

tpl->SetClassName(v8::String::NewSymbol("STDString"));
我們利用v8::String::NewSymbol()來創建一個用于屬性名稱的特殊類型字符串――這能為引擎的運作節約一點點時間。

在此之后,我們需要設定我們的類實例當中包含多少個字段:

tpl->InstanceTemplate()->SetInternalFieldCount(2);
我們擁有兩個方法――add()與toString(),因此我們將數量設置為2。現在我們可以將自己的方法添加到函數原型當中了:

tpl->PrototypeTemplate()->Set(v8::String::NewSymbol("add"), v8::FunctionTemplate::New(add)->GetFunction()); 
tpl->PrototypeTemplate()->Set(v8::String::NewSymbol("toString"), v8::FunctionTemplate::New(toString)->GetFunction());
這部分代碼量看起來比較大,但只要認真觀察大家就會發現其中的規律:我們利用tpl->PrototypeTemplate()->Set()來添加每一個方法。我們還利用v8::String::NewSymbol()為它們提供名稱與FunctionTemplate。

最后,我們可以將該構造函數安置于我們的constructor類屬性內的exports對象中:

constructor = v8::Persistent::New(tpl->GetFunction());   exports->Set(v8::String::NewSymbol("STDString"), constructor); }

New方法

現在我們要做的是定義一個與JavaScript Object.prototype.constructor運作效果相同的方法:

v8::Handle STDStringWrapper::New(const v8::Arguments& args) {

 我們首先需要為其創建一個范圍:

v8::HandleScope scope; 

在此之后,我們可以利用args對象的.IsConstructCall()方法來檢查該構造函數是否能夠利用new關鍵詞加以調用:

if (args.IsConstructCall()) { 

如果可以,我們首先如下所示將參數傳遞至std::string處:

v8::String::Utf8Value str(args[0]->ToString()); std::string s(*str);

……這樣我們就能將它傳遞到我們封裝類的構造函數當中了:

STDStringWrapper* obj = new STDStringWrapper(s);

在此之后,我們可以利用之前創建的該對象的.Wrap()方法(繼承自node::ObjectWrap)來將它分配給this變量:

obj->Wrap(args.This()); 

最后,我們可以返回這個新創建的對象:

return args.This(); 

如果該函數無法利用new進行調用,我們也可以直接調用構造函數。接下來,我們要做的是為參數計數設置一個常數:

} else {   const int argc = 1; 

現在我們需要利用自己的參數創建一個數組:

v8::Local argv[argc] = { args[0] }; 

然后將constructor->NewInstance方法的結果傳遞至scope.Close,這樣該對象就能在隨后發揮作用(scope.Close基本上允許大家通過將對象處理句柄移動至更高范圍的方式對其加以維持――這也是函數的起效方式):

    return scope.Close(constructor->NewInstance(argc, argv));   } } 

add方法

現在讓我們創建add方法,它的作用是允許大家向對象的內部std::string添加內容:

v8::Handle STDStringWrapper::add(const v8::Arguments& args) { 

首先,我們需要為我們的函數創建一個范圍,并像之前那樣把該參數轉換到std::string當中:

v8::HandleScope scope;   v8::String::Utf8Value str(args[0]->ToString()); std::string s(*str); 

現在我們需要對該對象進行拆包。我們之前也進行過這種反向封裝操作――這一次我們是要從this變量當中獲取指向對象的指針。

STDStringWrapper* obj = ObjectWrap::Unwrap(args.This()); 

接著我們可以訪問s_屬性并使用其.append()方法:

obj->s_->append(s); 

最后,我們返回s_屬性的當前值(需要再次使用scope.Close):

return scope.Close(v8::String::New(obj->s_->c_str())); 

由于v8::String::New()方法只能將char pointer作為值來接受,因此我們需要使用obj->s_->c_str()來加以獲取。

這時大家的插件文件夾中還應該創建出一個build目錄。

測試

現在我們可以對自己的插件進行測試了。在我們的插件目錄中創建一個test.js文件以及必要的編譯庫(大家可以直接略過.node擴展):

var addon = require('./build/Release/addon'); 

下一步,為我們的對象創建一個新實例:

var test = new addon.STDString('test'); 

下面再對其進行操作,例如添加或者將其轉化為字符串:

test.add('!'); console.log('test/'s contents: %s', test); 

在運行之后,大家應該在控制臺中看到以下執行結果:

結論

我希望大家能在閱讀了本教程之后打消顧慮,將創建與測試以C/C++庫為基礎的定制化Node.js插件視為一項無甚難度的任務。大家可以利用這種技術輕松將幾乎任何C/C++庫引入Node.js當中。如果大家愿意,還可以根據實際需求為插件添加更多功能。std::string當中提供大量方法,我們可以將它們作為練習素材。

實用鏈接

感興趣的朋友可以查看以下鏈接以獲取更多與Node.js插件開發、V8以及C事件循環庫相關的資源與詳細信息。

• Node.js插件說明文檔

• V8說明文檔

• libuv (C事件循環庫),來自GitHub

英文:http://code.tutsplus.com/tutorials/writing-nodejs-addons--cms-21771

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品女同一区二区三区在线播放| 一色桃子一区二区| 久久av资源网站| 国产精品视频最多的网站| 日韩国产高清污视频在线观看| 91高清视频免费观看| 欧美激情国产高清| 精品成人国产在线观看男人呻吟| 日韩欧美大尺度| 亚洲全黄一级网站| 日本电影亚洲天堂| 亚洲最新av网址| 日韩视频中文字幕| 91中文精品字幕在线视频| 亚洲精品91美女久久久久久久| 亚洲情综合五月天| 97激碰免费视频| 亚洲精品日韩激情在线电影| 欧美高清在线播放| 日韩成人av一区| 欧美国产视频日韩| 日韩欧美高清视频| 日韩大片免费观看视频播放| 午夜精品蜜臀一区二区三区免费| 高清欧美一区二区三区| 国产精品吹潮在线观看| 成人中心免费视频| 大伊人狠狠躁夜夜躁av一区| 亚洲精品视频中文字幕| 亚洲free性xxxx护士hd| 中文字幕日韩视频| 国产精品一区二区av影院萌芽| 欧美乱大交xxxxx另类电影| 日韩影视在线观看| 亚洲www在线| 亚洲深夜福利在线| 亚洲免费成人av电影| 午夜精品久久17c| 国产美女精品免费电影| 91精品啪在线观看麻豆免费| 国产精品视频在线播放| 丰满岳妇乱一区二区三区| 亚洲欧美日韩中文在线制服| 亚洲福利小视频| 国产亚洲欧洲高清一区| 成人福利网站在线观看| 欧美亚洲日本网站| 中文字幕亚洲综合久久| 热久久99这里有精品| 96pao国产成视频永久免费| 中文字幕av一区| 色婷婷**av毛片一区| 欧美日韩xxxxx| 久久久久99精品久久久久| 九九热99久久久国产盗摄| 欧美国产在线电影| 中文字幕日韩综合av| 一区二区三区四区精品| 精品一区二区三区四区在线| 成人av在线天堂| 91免费视频网站| 成人网中文字幕| 91香蕉国产在线观看| 欧美日韩综合视频| 久久亚洲精品成人| 啪一啪鲁一鲁2019在线视频| 国产精品福利网| 精品高清一区二区三区| 欧美视频中文字幕在线| 日韩亚洲一区二区| 欧美影院在线播放| 国产成+人+综合+亚洲欧洲| 国产z一区二区三区| 欧美视频一区二区三区…| 九九精品在线观看| 亚洲精品视频网上网址在线观看| 精品国偷自产在线视频99| 性欧美在线看片a免费观看| 国产一区二区丝袜高跟鞋图片| 日本精品久久久| 久久中文字幕在线视频| 国产精品美腿一区在线看| 韩国欧美亚洲国产| 欧美丰满老妇厨房牲生活| 亚洲精品一区二区三区不| 亚洲系列中文字幕| 91丝袜美腿美女视频网站| 综合网日日天干夜夜久久| 亚洲最新在线视频| 亚洲视频一区二区| 亚洲美女av黄| 亚洲精品xxx| 中文字幕亚洲一区二区三区| www.99久久热国产日韩欧美.com| 亚洲成人精品久久久| 在线日韩av观看| 欧美大片大片在线播放| 国产精品免费网站| 国产精品自产拍在线观看中文| www.日韩系列| 91精品久久久久久久久青青| 亚洲欧美国产一本综合首页| 国产一区二区三区在线播放免费观看| 色久欧美在线视频观看| 在线播放日韩专区| 91精品久久久久久久| 亚洲国产精彩中文乱码av在线播放| 欧美激情三级免费| 欧美成人免费全部| 欧美成人小视频| 午夜精品蜜臀一区二区三区免费| 成人av电影天堂| 国产一级揄自揄精品视频| 久久免费成人精品视频| 欧美丰满少妇xxxxx做受| 欧美成人黑人xx视频免费观看| 九九热r在线视频精品| 中文字幕亚洲国产| 国模精品一区二区三区色天香| 91色p视频在线| 国模极品一区二区三区| 亚洲人成欧美中文字幕| 久久免费观看视频| 欧美在线性视频| 成人国产在线视频| 国产婷婷97碰碰久久人人蜜臀| 欧美巨乳美女视频| 日产日韩在线亚洲欧美| 2019中文字幕在线观看| 国产不卡av在线免费观看| 最近中文字幕2019免费| 亚洲精品久久久久久下一站| 久久精品成人一区二区三区| 欧美大片在线看| 国产精品久久久久久婷婷天堂| 欧美大片免费观看在线观看网站推荐| 国产一区二区三区高清在线观看| 国产精品视频999| 国产精品夫妻激情| 成人综合网网址| 国产精品电影在线观看| 一区二区av在线| 高跟丝袜一区二区三区| 亚洲精品美女在线观看| 92版电视剧仙鹤神针在线观看| 麻豆国产va免费精品高清在线| 午夜精品一区二区三区在线播放| 亚洲毛片一区二区| 亚洲资源在线看| 欧美疯狂做受xxxx高潮| 亚洲自拍小视频| 欧美在线视频观看| 韩国国内大量揄拍精品视频| 欧美大胆a视频| 川上优av一区二区线观看| 亚洲最大的av网站| 久久久www成人免费精品| 亚洲欧洲日本专区| 日本一区二区不卡| 国产日韩欧美黄色| 欧美黑人xxxx| 精品久久久国产| 亚洲第一国产精品| 国产精品99久久久久久白浆小说|