欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2015年06月23日 11:43:49   投稿:goldensun  
這篇文章主要介紹了使用Node.js為其他程序編寫擴展的基本方法 ,文中示例是通過Node讓JavaScript代碼與C++應(yīng)用產(chǎn)生交互,需要的朋友可以參考下

 準備開始

首先我們用下面的目錄結(jié)構(gòu)來創(chuàng)建一個節(jié)點通知(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 生成.

現(xiàn)在讓我來創(chuàng)建測試腳本demo.js 和決定我們擴展的API前期看起來應(yīng)該像:
 

// 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/16x16
notification.send("Notification message");

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

為了創(chuàng)建一個Node.js擴展,我們需要編寫一個繼承node::ObjectWrap的C++類。 ObjectWrap 實現(xiàn)了讓我們更容易與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);
}

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

    聲明構(gòu)造函數(shù),并將其綁定到我們的目標變量。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);

現(xiàn)在我們的Init()方法看起來應(yīng)該是這樣的:
 
// Our constructor
static 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

構(gòu)造器方法: New()

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

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

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

// this.title
static 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.icon
static 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 引用,然后使用對象的屬性來構(gòu)建通知并顯示。
 

// 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 是一個構(gòu)建工具,用來編譯 Node 的擴展,這是 waf 的基本封裝。構(gòu)建過程可通過名為 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']

現(xiàn)在我們已經(jīng)準備好要開始構(gòu)建了,在頂級目錄下運行如下命令:

 
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社區(qū)分享你的努力的成果呢? 這才是npm主要的用途: 使它更加容易擴展和分發(fā).

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

{
 // 擴展的名稱 (不要在名稱中包含node 或者 js, 這是隱式關(guān)鍵字).
 // 這是通過require() 導入擴展的名稱.
 
 "name" : "notify",
 
 // Version should be http://semver.org/ compliant
 
 "version" : "v0.1.0"
 
 // 這些腳本將在調(diào)用npm安裝和npm卸載的時候運行.
 
 , "scripts" : {
   "preinstall" : "node-waf configure && node-waf build"
   , "preuninstall" : "rm -rf build/*"
  }
 
 // 這是構(gòu)建我們擴展的相對路徑.
 
 , "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"
  }
}

關(guān)于package.json 格式的更多細節(jié), 可以通過 npm help json 獲取文檔. 注意 大多數(shù)字段都是可選的.


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

假設(shè)你寫了一個很酷的擴展, 你可能想要在中央npm庫發(fā)布到網(wǎng)上. 首先你要先創(chuàng)建一個賬戶:

 

$ npm adduser

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

 
$ npm publish

就是這樣, 你的包現(xiàn)在已經(jīng)可以被任何人通過npm install 你的包名命令來安裝了.

 

相關(guān)文章

  • Node如何后臺數(shù)據(jù)庫使用增刪改查功能

    Node如何后臺數(shù)據(jù)庫使用增刪改查功能

    這篇文章主要介紹了Node如何后臺數(shù)據(jù)庫使用增刪改查功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Electron 調(diào)用命令行(cmd)

    Electron 調(diào)用命令行(cmd)

    這篇文章主要介紹了Electron 調(diào)用命令行(cmd),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • Node.js中DNS模塊學習總結(jié)

    Node.js中DNS模塊學習總結(jié)

    本篇文章給大家詳細介紹了Node.js中DNS模塊的相關(guān)知識點,以及相關(guān)的實例代碼做了分享,有興趣的朋友參考下。
    2018-02-02
  • Node.js中使用Buffer編碼、解碼二進制數(shù)據(jù)詳解

    Node.js中使用Buffer編碼、解碼二進制數(shù)據(jù)詳解

    這篇文章主要介紹了Node.js中使用Buffer編碼、解碼二進制數(shù)據(jù)詳解,Buffer支持ascii、utf8、ucs2、base64等編碼格式,需要的朋友可以參考下
    2014-08-08
  • 深入解析nodejs HTTP服務(wù)

    深入解析nodejs HTTP服務(wù)

    本篇文章主要介紹了深入解析nodejs HTTP服務(wù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • node.js中process進程的概念和child_process子進程模塊的使用方法示例

    node.js中process進程的概念和child_process子進程模塊的使用方法示例

    這篇文章主要介紹了node.js中process進程的概念和child_process子進程模塊的使用方法,結(jié)合實例形式分析了node.js中process進程和child_process子進程模塊相關(guān)概念、原理、使用方法及操作注意事項,需要的朋友可以參考下
    2020-02-02
  • node.js中的fs.readdirSync方法使用說明

    node.js中的fs.readdirSync方法使用說明

    這篇文章主要介紹了node.js中的fs.readdirSync方法使用說明,本文介紹了fs.readdirSync方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • NodeJS實現(xiàn)不可逆加密與密碼密文保存的方法

    NodeJS實現(xiàn)不可逆加密與密碼密文保存的方法

    這篇文章主要介紹了NodeJS實現(xiàn)不可逆加密與密碼密文保存的方法,簡單講述了不可逆加密與密碼密文保存的原理并結(jié)合實例形式分析了nodejs相關(guān)加密操作實現(xiàn)技巧,需要的朋友可以參考下
    2018-03-03
  • Node.js使用多進程提高任務(wù)執(zhí)行效率

    Node.js使用多進程提高任務(wù)執(zhí)行效率

    在Node.JS中使用多進程非常簡單,合理使用多進程,可以解放硬件的能力,讓軟件的運行效率得到肉眼可見的提升。本文詳細講解了Node.js使用多進程提高任務(wù)執(zhí)行效率的方法,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • nodejs+express實現(xiàn)文件上傳下載管理網(wǎng)站

    nodejs+express實現(xiàn)文件上傳下載管理網(wǎng)站

    這篇文章主要為大家詳細介紹了nodejs+express實現(xiàn)文件上傳下載管理的網(wǎng)站,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03

最新評論