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

首頁 > 編程 > JavaScript > 正文

使用Node.js為其他程序編寫擴展的基本方法

2019-11-20 12:11:31
字體:
來源:轉載
供稿:網友

 準備開始

首先我們用下面的目錄結構來創建一個節點通知(node-notify)文件夾.
 

復制代碼 代碼如下:

.
|-- build/                   # This is where our extension is built.
|-- demo/
|   `-- demo.js              # This is a demo Node.js script to test our extension.
|-- src/
|   `-- node_gtknotify.cpp   # This is the where we do the mapping from C++ to Javascript.
`-- wscript                  # This is our build configuration used by node-waf

這個看起來很漂亮的tree 用通用的 tree 生成.

現在讓我來創建測試腳本demo.js 和決定我們擴展的API前期看起來應該像:
 

// This loads our extension on the notify variable.// It will only load a constructor function, notify.notification().var notify = require("../build/default/gtknotify.node"); // path to our extension var notification = new notify.notification();notification.title = "Notification title";notification.icon = "emblem-default"; // see /usr/share/icons/gnome/16x16notification.send("Notification message");

編寫我們的Node.js擴展
Init方法

為了創建一個Node.js擴展,我們需要編寫一個繼承node::ObjectWrap的C++類。 ObjectWrap 實現了讓我們更容易與Javascript交互的公共方法

我們先來編寫類的基本框架:
 

#include <v8.h> // v8 is the Javascript engine used by QNode#include <node.h>// We will need the following libraries for our GTK+ notification#include <string>#include <gtkmm.h>#include <libnotifymm.h> using namespace v8; class Gtknotify : node::ObjectWrap { private: public:  Gtknotify() {}  ~Gtknotify() {}  static void Init(Handle<Object> target) {   // This is what Node will call when we load the extension through require(), see boilerplate code below.  }}; /* * WARNING: Boilerplate code ahead. * * See https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native-extensions/ & http://www.freebsd.org/cgi/man.cgi?query=dlsym *  * Thats it for actual interfacing with v8, finally we need to let Node.js know how to dynamically load our code. * Because a Node.js extension can be loaded at runtime from a shared object, we need a symbol that the dlsym function can find, * so we do the following:  */ v8::Persistent<FunctionTemplate> Gtknotify::persistent_function_template;extern "C" { // Cause of name mangling in C++, we use extern C here static void init(Handle<Object> target) {  Gtknotify::Init(target); } // @see http://github.com/ry/node/blob/v0.2.0/src/node.h#L101 NODE_MODULE(gtknotify, init);}

現在,我們必須把下面的代碼編寫到我們的Init()方法中:

    聲明構造函數,并將其綁定到我們的目標變量。var n = require("notification");將綁定notification() 到 n:n.notification().

// Wrap our C++ New() method so that it's accessible from Javascript  // This will be called by the new operator in Javascript, for example: new notification();  v8::Local<FunctionTemplate> local_function_template = v8::FunctionTemplate::New(New);     // Make it persistent and assign it to persistent_function_template which is a static attribute of our class.  Gtknotify::persistent_function_template = v8::Persistent<FunctionTemplate>::New(local_function_template);     // Each JavaScript object keeps a reference to the C++ object for which it is a wrapper with an internal field.  Gtknotify::persistent_function_template->InstanceTemplate()->SetInternalFieldCount(1); // 1 since a constructor function only references 1 object  // Set a "class" name for objects created with our constructor  Gtknotify::persistent_function_template->SetClassName(v8::String::NewSymbol("Notification"));     // Set the "notification" property of our target variable and assign it to our constructor function  target->Set(String::NewSymbol("notification"), Gtknotify::persistent_function_template->GetFunction());

    聲明屬性:n.title 和n.icon.
 

  // Set property accessors  // SetAccessor arguments: Javascript property name, C++ method that will act as the getter, C++ method that will act as the setter  Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle);  Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("icon"), GetIcon, SetIcon);  // For instance, n.title = "foo" will now call SetTitle("foo"), n.title will now call GetTitle()
    聲明原型方法:n.send()
   
  // This is a Node macro to help bind C++ methods to Javascript methods (see https://github.com/joyent/node/blob/v0.2.0/src/node.h#L34)  // Arguments: our constructor function, Javascript method name, C++ method name  NODE_SET_PROTOTYPE_METHOD(Gtknotify::persistent_function_template, "send", Send);
現在我們的Init()方法看起來應該是這樣的:
 
// Our constructorstatic v8::Persistent<FunctionTemplate> persistent_function_template; static void Init(Handle<Object> target) { v8::HandleScope scope; // used by v8 for garbage collection  // Our constructor v8::Local<FunctionTemplate> local_function_template = v8::FunctionTemplate::New(New); Gtknotify::persistent_function_template = v8::Persistent<FunctionTemplate>::New(local_function_template); Gtknotify::persistent_function_template->InstanceTemplate()->SetInternalFieldCount(1); // 1 since this is a constructor function Gtknotify::persistent_function_template->SetClassName(v8::String::NewSymbol("Notification"));  // Our getters and setters Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle); Gtknotify::persistent_function_template->InstanceTemplate()->SetAccessor(String::New("icon"), GetIcon, SetIcon);  // Our methods NODE_SET_PROTOTYPE_METHOD(Gtknotify::persistent_function_template, "send", Send);  // Binding our constructor function to the target variable target->Set(String::NewSymbol("notification"), Gtknotify::persistent_function_template->GetFunction());}
剩下要做的就是編寫我們在Init方法中用的C++方法:New,GetTitle,SetTitle,GetIcon,SetIcon,Send

構造器方法: New()

New() 方法創建了我們自定義類的新實例(一個 Gtknotify 對象),并設置一些初始值,然后返回該對象的 JavaScript 處理。這是 JavaScript 使用 new 操作符調用構造函數的期望行為。

 std::string title;std::string icon; // new notification()static Handle<Value> New(const Arguments& args) { HandleScope scope; Gtknotify* gtknotify_instance = new Gtknotify(); // Set some default values gtknotify_instance->title = "Node.js"; gtknotify_instance->icon = "terminal";  // Wrap our C++ object as a Javascript object gtknotify_instance->Wrap(args.This());  return args.This();}getters 和 setters: GetTitle(), SetTitle(), GetIcon(), SetIcon()

下面主要是一些樣板代碼,可以歸結為 C++ 和 JavaScript (v8) 之間的值轉換。
 

// this.titlestatic v8::Handle<Value> GetTitle(v8::Local<v8::String> property, const v8::AccessorInfo& info) { // Extract the C++ request object from the JavaScript wrapper. Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder()); return v8::String::New(gtknotify_instance->title.c_str());}// this.title=static void SetTitle(Local<String> property, Local<Value> value, const AccessorInfo& info) { Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder()); v8::String::Utf8Value v8str(value); gtknotify_instance->title = *v8str;}// this.iconstatic v8::Handle<Value> GetIcon(v8::Local<v8::String> property, const v8::AccessorInfo& info) { // Extract the C++ request object from the JavaScript wrapper. Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder()); return v8::String::New(gtknotify_instance->icon.c_str());}// this.icon=static void SetIcon(Local<String> property, Local<Value> value, const AccessorInfo& info) { Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(info.Holder()); v8::String::Utf8Value v8str(value); gtknotify_instance->icon = *v8str;}

原型方法: Send()

首先我們抽取 C++ 對象的 this 引用,然后使用對象的屬性來構建通知并顯示。
 

// this.send()static v8::Handle<Value> Send(const Arguments& args) { v8::HandleScope scope; // Extract C++ object reference from "this" Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(args.This());  // Convert first argument to V8 String v8::String::Utf8Value v8str(args[0]);  // For more info on the Notify library: http://library.gnome.org/devel/libnotify/0.7/NotifyNotification.html Notify::init("Basic"); // Arguments: title, content, icon Notify::Notification n(gtknotify_instance->title.c_str(), *v8str, gtknotify_instance->icon.c_str()); // *v8str points to the C string it wraps // Display the notification n.show(); // Return value return v8::Boolean::New(true);}

編譯擴展

node-waf 是一個構建工具,用來編譯 Node 的擴展,這是 waf 的基本封裝。構建過程可通過名為 wscript 的文件進行配置。
 

def set_options(opt): opt.tool_options("compiler_cxx") def configure(conf): conf.check_tool("compiler_cxx") conf.check_tool("node_addon") # This will tell the compiler to link our extension with the gtkmm and libnotifymm libraries. conf.check_cfg(package='gtkmm-2.4', args='--cflags --libs', uselib_store='LIBGTKMM') conf.check_cfg(package='libnotifymm-1.0', args='--cflags --libs', uselib_store='LIBNOTIFYMM') def build(bld): obj = bld.new_task_gen("cxx", "shlib", "node_addon") obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall"] # This is the name of our extension. obj.target = "gtknotify" obj.source = "src/node_gtknotify.cpp" obj.uselib = ['LIBGTKMM', 'LIBNOTIFYMM']

現在我們已經準備好要開始構建了,在頂級目錄下運行如下命令:

 
node-waf configure && node-waf build

如果一切正常,我們將得到編譯過的擴展,位于:./build/default/gtknotify.node ,來試試:
 

$ node> var notif = require('./build/default/gtknotify.node');> n = new notif.notification();{ icon: 'terminal', title: 'Node.js' }> n.send("Hello World!");true

上述的代碼將在你的屏幕右上方顯示一個通知信息。

打成npm包

這是非常酷的, 但是怎樣與Node社區分享你的努力的成果呢? 這才是npm主要的用途: 使它更加容易擴展和分發.

打npm的擴展包是非常簡單的. 你所要做的就是在你的頂級目錄中創建一個包含你的擴展信息的文件package.json :
 

{ // 擴展的名稱 (不要在名稱中包含node 或者 js, 這是隱式關鍵字). // 這是通過require() 導入擴展的名稱.  "name" : "notify",  // Version should be http://semver.org/ compliant  "version" : "v0.1.0"  // 這些腳本將在調用npm安裝和npm卸載的時候運行.  , "scripts" : {   "preinstall" : "node-waf configure && node-waf build"   , "preuninstall" : "rm -rf build/*"  }  // 這是構建我們擴展的相對路徑.  , "main" : "build/default/gtknotify.node"  // 以下是可選字段:  , "description" : "Description of the extension...." , "homepage" : "https://github.com/olalonde/node-notify" , "author" : {   "name" : "Olivier Lalonde"   , "email" : "olalonde@gmail.com"   , "url" : "http://www.syskall.com/"  } , "repository" : {   "type" : "git"   , "url" : "https://github.com/olalonde/node-notify.git"  }}

關于package.json 格式的更多細節, 可以通過 npm help json 獲取文檔. 注意 大多數字段都是可選的.


你現在可以在你的頂級目錄中通過運行npm install 來安裝你的新的npm包了. 如果一切順利的話, 應該可以簡單的加載你的擴展 var notify = require('你的包名');. 另外一個比較有用的命令式 npm link 通過這個命令你可以創建一個到你開發目錄的鏈接,當你的代碼發生變化時不必每次都去安裝/卸載.

假設你寫了一個很酷的擴展, 你可能想要在中央npm庫發布到網上. 首先你要先創建一個賬戶:

 

$ npm adduser

下一步, 回到你的根目錄編碼并且運行:

 $ npm publish

就是這樣, 你的包現在已經可以被任何人通過npm install 你的包名命令來安裝了.

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产suv精品一区二区三区88区| 亚洲第一福利视频| 久久免费视频这里只有精品| 亚洲精品suv精品一区二区| 国产精品久久久久久久久久小说| 色偷偷88888欧美精品久久久| 欧美性xxxx极品hd欧美风情| 国产在线精品成人一区二区三区| 国产一区二区三区久久精品| 国产精品爽爽爽爽爽爽在线观看| 久久91亚洲精品中文字幕奶水| 精品少妇一区二区30p| 欧美日韩激情网| 欧美电影院免费观看| 91精品国产自产在线| 国产亚洲精品久久久久久| 亚洲毛茸茸少妇高潮呻吟| 91久久嫩草影院一区二区| 欧美亚洲第一区| 久久精品99久久久香蕉| 久久亚洲综合国产精品99麻豆精品福利| 日韩欧美有码在线| 国产精品中文字幕久久久| 亚洲久久久久久久久久久| 性欧美长视频免费观看不卡| 亚洲国模精品私拍| 色偷偷亚洲男人天堂| 国产丝袜高跟一区| 亚洲大胆人体av| 亚洲精品久久久久国产| 亚洲第一色在线| 精品日本高清在线播放| 欧美黑人一区二区三区| 国产成人精品一区二区在线| 国产91网红主播在线观看| 久久久久久综合网天天| 亚洲白虎美女被爆操| 一区二区福利视频| 91夜夜揉人人捏人人添红杏| 中文字幕精品av| 亚洲精品久久久久久久久久久| 欧美日韩国产123| 美日韩精品视频免费看| 91精品美女在线| 欧美激情影音先锋| 欧美专区在线视频| 丝袜亚洲欧美日韩综合| 亚洲欧美日韩在线一区| 不卡伊人av在线播放| 日韩av在线免费播放| 亚洲最大成人网色| 69久久夜色精品国产69| 欧美成人剧情片在线观看| 欧美日韩999| 久久99久久99精品免观看粉嫩| 伊人亚洲福利一区二区三区| 欧美二区乱c黑人| 亚洲第一精品久久忘忧草社区| 久久九九全国免费精品观看| 九九热这里只有精品6| 亚洲精品电影久久久| 国产日韩精品电影| 黑丝美女久久久| 久久久久久久久久久成人| 欧美专区国产专区| 在线观看欧美成人| 亚洲精品二三区| 日韩av在线精品| 亚洲国产日韩欧美在线动漫| 欧美日韩精品二区| 91视频88av| 91精品国产高清久久久久久| 日韩免费av片在线观看| 国产精品久久久久久搜索| 久久综合伊人77777| 91在线高清视频| 久久好看免费视频| 欧美激情亚洲国产| 在线观看精品自拍私拍| 国产精品美女网站| 欧美日韩亚洲视频一区| 亚洲第一天堂无码专区| 亚洲欧美精品一区| 日韩大胆人体377p| 精品国产乱码久久久久酒店| 欧美大片网站在线观看| 国产精品久久久久久久久久新婚| 2019亚洲男人天堂| 欧美午夜性色大片在线观看| 久久久久久亚洲精品| 国产免费一区二区三区香蕉精| 一区二区三区四区视频| 欧美性资源免费| 91精品国产高清自在线看超| 57pao国产成人免费| 91在线播放国产| 日韩成人激情视频| 亚洲精品欧美一区二区三区| 欧美精品少妇videofree| 国产成人免费av| 日韩一区二区在线视频| 一区二区三区精品99久久| 日本三级韩国三级久久| 精品美女国产在线| 久久久亚洲国产| 欧美亚洲视频一区二区| 国产91精品青草社区| 在线观看日韩专区| 亚洲免费高清视频| 成人午夜一级二级三级| 国产日本欧美在线观看| 欧美高清理论片| 中文字幕精品在线| 国产mv免费观看入口亚洲| 欧美日本高清视频| 在线成人中文字幕| 国产成人+综合亚洲+天堂| 欧美激情第一页xxx| 亚洲国产高清福利视频| 日韩av一区在线| 庆余年2免费日韩剧观看大牛| 国产在线98福利播放视频| 4k岛国日韩精品**专区| 亚洲黄色av女优在线观看| 国产欧美精品久久久| 深夜成人在线观看| 日韩中文字幕在线观看| 欧美激情视频一区| 久国内精品在线| 国产精品高潮在线| 国产精品久久久999| 欧美日韩国产综合视频在线观看中文| 日韩av资源在线播放| 久久精品视频免费播放| 国产精品入口夜色视频大尺度| 日韩在线视频一区| 亚洲精品久久在线| 亚洲国产小视频| 欧美激情在线视频二区| 最近2019中文字幕一页二页| 亚洲电影免费观看高清完整版| 成人综合网网址| 国产精品激情av电影在线观看| 成人在线观看视频网站| 久久网福利资源网站| 欧美疯狂xxxx大交乱88av| 国产成人精品电影久久久| 国产亚洲精品久久久优势| 久久91亚洲精品中文字幕| 国内精品伊人久久| 日韩视频亚洲视频| 欧美成人中文字幕在线| 亚洲第一网站男人都懂| 国产成人精品久久亚洲高清不卡| 精品国模在线视频| 日韩欧美中文在线| 亚洲精品乱码久久久久久金桔影视| 国产精品流白浆视频| 精品久久久免费| 国产一区二区日韩精品欧美精品| 日韩成人激情影院| 国产精品美女www| 国产精品入口免费视| 激情懂色av一区av二区av|