Cara asas untuk menulis sambungan untuk atur cara lain menggunakan Node.js_node.js

WBOY
Lepaskan: 2016-05-16 15:53:26
asal
1187 orang telah melayarinya

Sedia untuk bermula

Mula-mula kami menggunakan struktur direktori berikut untuk mencipta folder pemberitahuan nod.

Salin kod Kod adalah seperti berikut:

.
|-- bina/                                                         # Di sinilah sambungan kami dibina.
|-- demo/
|. `-- demo.js # Ini ialah skrip Node.js demo untuk menguji sambungan kami.
|-- src/
|. `-- node_gtknotify.cpp # Di sinilah kami melakukan pemetaan dari C ke Javascript.
`-- wscript                                 # Ini ialah konfigurasi binaan kami yang digunakan oleh nod-waf

Pokok yang kelihatan cantik ini dijana menggunakan pokok generik.

Sekarang izinkan saya mencipta skrip ujian demo.js dan tentukan rupa API sambungan kami di hadapan:

// 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");
Salin selepas log masuk

Menulis sambungan Node.js kami
Kaedah init

Untuk mencipta sambungan Node.js, kita perlu menulis kelas C yang mewarisi nod::ObjectWrap. ObjectWrap melaksanakan kaedah awam yang memudahkan kita berinteraksi dengan Javascript

Mari kita tulis rangka kerja asas kelas dahulu:

#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&#63;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);
}
Salin selepas log masuk

Sekarang, kita perlu menulis kod berikut ke dalam kaedah Init() kami:

Isytiharkan pembina dan ikat pada pembolehubah sasaran kami. var n = require("notification"); akan mengikat notification() kepada 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());

Salin selepas log masuk

Atribut pengisytiharan: n.title dan 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()

Salin selepas log masuk
Isytihar kaedah prototaip: 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);

Salin selepas log masuk
Sekarang kaedah Init() kami sepatutnya kelihatan seperti ini:

// 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());
}

Salin selepas log masuk
Apa yang perlu dilakukan ialah menulis kaedah C yang kami gunakan dalam kaedah Init: Baharu, GetTitle, SetTitle, GetIcon, SetIcon, Send

Kaedah pembina: Baharu()

Kaedah

New() mencipta contoh baharu kelas tersuai kami (objek Gtknotify), menetapkan beberapa nilai awal dan kemudian mengembalikan pengendali JavaScript untuk objek itu. Ini ialah tingkah laku yang dijangkakan JavaScript memanggil pembina menggunakan operator baharu.

 
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()
Salin selepas log masuk

Apa yang berikut adalah kebanyakannya kod boilerplate yang bermuara kepada penukaran nilai antara C dan JavaScript (v8).

// 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;
}
Salin selepas log masuk

Kaedah prototaip: Hantar()

Mula-mula kami mengekstrak rujukan objek C ini, dan kemudian menggunakan sifat objek untuk membina pemberitahuan dan memaparkannya.

// 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);
}
Salin selepas log masuk

Kompilasi sambungan

node-waf ialah alat binaan yang digunakan untuk menyusun sambungan Nod, yang merupakan pakej asas waf. Proses binaan boleh dikonfigurasikan melalui fail yang dipanggil 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']
Salin selepas log masuk

Sekarang kita sudah bersedia untuk mula membina, jalankan arahan berikut dalam direktori peringkat atas:


konfigurasi nod-waf && binaan nod-waf

Jika semuanya berjalan lancar, kami akan mendapat sambungan terkumpul, yang terletak di: ./build/default/gtknotify.node, mari cuba:

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

Kod di atas akan memaparkan mesej pemberitahuan di penjuru kanan sebelah atas skrin anda.

Dibungkus ke dalam pakej npm

Ini sangat hebat, tetapi bagaimana anda berkongsi hasil usaha anda dengan komuniti Node Ini adalah tujuan utama npm: menjadikannya lebih mudah untuk dilanjutkan dan diedarkan.

Membungkus sambungan dengan npm adalah sangat mudah anda hanya perlu membuat pakej fail.json dalam direktori peringkat teratas anda yang mengandungi maklumat sambungan anda:

{
 // 扩展的名称 (不要在名称中包含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"
  }
}
Salin selepas log masuk

Untuk butiran lanjut tentang format package.json, dokumentasi boleh diperolehi melalui npm help json Ambil perhatian bahawa kebanyakan medan adalah pilihan.


Anda kini boleh memasang pakej npm baharu anda dengan menjalankan pemasangan npm dalam direktori peringkat teratas anda Jika semuanya berjalan lancar, anda sepatutnya boleh memuatkan sambungan anda var notify = require('nama pakej anda'); pautan npm. Dengan arahan ini anda boleh membuat pautan ke direktori pembangunan anda, jadi anda tidak perlu memasang/menyahpasang setiap kali kod anda berubah

Andaikan anda menulis sambungan yang menarik, anda mungkin mahu menerbitkannya dalam talian dalam repositori npm pusat Mula-mula anda perlu membuat akaun:


$ npm adduser
Salin selepas log masuk

下一步, 回到你的根目录编码并且运行:

 
$ npm publish
Salin selepas log masuk

就是这样, 你的包现在已经可以被任何人通过npm install 你的包名命令来安装了.

 

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan