萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> 使用Node.js為其他程序編寫擴展的基本方法

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

   這篇文章主要介紹了使用Node.js為其他程序編寫擴展的基本方法 ,文中示例是通過Node讓JavaScript代碼與C++應用產生交互,需要的朋友可以參考下

  准備開始

  首先我們用下面的目錄結構來創建一個節點通知(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前期看起來應該像:

  ?

  1

  2

  3

  4

  5

  6

  7

  8// 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方法

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

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

  ?

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  23

  24

  25

  26

  27

  28

  29

  30

  31

  32

  33

  34

  35

  36

  37#include // v8 is the Javascript engine used by QNode

  #include

  // We will need the following libraries for our GTK+ notification

  #include

  #include

  #include

  using namespace v8;

  class Gtknotify : node::ObjectWrap {

  private:

  public:

  Gtknotify() {}

  ~Gtknotify() {}

  static void Init(Handle 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 Gtknotify::persistent_function_template;

  extern "C" { // Cause of name mangling in C++, we use extern C here

  static void init(Handle 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().

  ?

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14// 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 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::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.

  ?

  1

  2

  3

  4

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

  ?

  1

  2

  3// 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()方法看起來應該是這樣的:

  ?

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22// Our constructor

  static v8::Persistent persistent_function_template;

  static void Init(Handle target) {

  v8::HandleScope scope; // used by v8 for garbage collection

  // Our constructor

  v8::Local local_function_template = v8::FunctionTemplate::New(New);

  Gtknotify::persistent_function_template = v8::Persistent::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

copyright © 萬盛學電腦網 all rights reserved