您现在的位置: 万盛学电脑网 >> 程序编程 >> 脚本专题 >> javascript >> 正文

使用Node.js为其他程序编写扩展的基本方法

作者:佚名    责任编辑:admin    更新时间:2022-06-22

   这篇文章主要介绍了使用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