iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >使用Node.js为其他程序编写扩展的基本方法
  • 272
分享到

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

程序方法Node 2022-06-04 17:06:42 272人浏览 独家记忆
摘要

准备开始 首先我们用下面的目录结构来创建一个节点通知(node-notify)文件夹. . |-- build/ # This is where our

准备开始

首先我们用下面的目录结构来创建一个节点通知(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/16x16
notification.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.
  }
};
 

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

构造器方法: 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.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 引用,然后使用对象的属性来构建通知并显示。


// 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 你的包名命令来安装了.

--结束END--

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

本文链接: http://www.lsjlt.com/news/12288.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何使用Cython为Python编写更快的C扩展
    本篇文章为大家展示了如何使用Cython为Python编写更快的C扩展,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。在我们这个包含了 7 个 PyPI 库的系列文章中学习解决常见的 Python 问...
    99+
    2023-06-16
  • 汇编基础程序编写的方法是什么
    这篇文章主要介绍“汇编基础程序编写的方法是什么”,在日常操作中,相信很多人在汇编基础程序编写的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”汇编基础程序编写的方法是什么”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-25
  • 微信小程序使用扩展组件库WeUI的方法
    本篇内容介绍了“微信小程序使用扩展组件库WeUI的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 学习参考2.NodeJs初始化这里...
    99+
    2023-06-30
  • Node.js方法的编写方法和使用技巧有哪些
    这篇文章主要讲解了“Node.js方法的编写方法和使用技巧有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Node.js方法的编写方法和使用技巧有哪些”吧!一、Node.js方法的编写方...
    99+
    2023-07-05
  • PHP应用程序的打包:使用Bash脚本还是其他工具?
    在开发PHP应用程序时,我们通常需要将代码打包为一个可执行文件或者一个压缩包,以便于部署和分发。而在打包过程中,我们需要考虑许多因素,比如文件结构、依赖关系、版本管理等。那么,我们应该使用什么工具来打包我们的PHP应用程序呢? 在这篇文章...
    99+
    2023-11-06
    linux 打包 bash
  • linux应用程序的编写方法是什么
    Linux应用程序的编写方法可以分为以下几个步骤:1. 选择编程语言:Linux支持多种编程语言,如C、C++、Python、Jav...
    99+
    2023-09-22
    linux
  • 如何在go教程中使用shell编写可扩展的日志记录器?
    在软件开发过程中,日志记录是非常重要的一环,因为它可以帮助我们快速定位和解决问题。在go语言中,使用标准库提供的log包可以很方便地进行日志记录。但是,当我们需要更加复杂的日志记录功能时,我们需要使用一些第三方库或自己编写一些代码来实现。...
    99+
    2023-06-22
    教程 日志 shell
  • 在远程 selenium 中使用 golang 加载 Chrome 扩展的方法
    IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天编程网给大家整理了《在远程 selenium 中...
    99+
    2024-04-04
  • 使用 Golang 编写计算数据集方差的程序
    标题:使用 Golang 计算数据集的方差 方差(Variance)是描述数据分布离散程度的一种统计量,在实际数据分析中具有重要的意义。本文将介绍如何使用 Golang 编程语言计算给...
    99+
    2024-02-24
    计算 golang 方差
  • Linux上打包PHP应用程序的最佳实践:使用Bash脚本还是其他工具?
    随着PHP应用程序的不断发展,如何在Linux上打包PHP应用程序成为了一个非常重要的问题。常见的打包工具有Bash脚本、Phar、Docker等。那么,使用Bash脚本还是其他工具呢?本文将从实际案例出发,探讨打包PHP应用程序的最佳实...
    99+
    2023-11-06
    linux 打包 bash
  • 笔记本摄像头被其他程序占用怎么办 摄像头被占用Windows7/8解决方法
    经常遇到友友问说笔记本摄像头被占用了怎么办?相信不少用笔记本的亲都遇到过这种问题,小编来为您分享一篇详细的解决方案吧! 摄像头为什么会被占用 分析原因应该是第三方程序占用摄像头,或是被其他优化软件优化掉了,导致摄像头无法...
    99+
    2023-06-01
    摄像头 Windows7 Windows8 解决 程序 方法
  • Java中线程的基本方法使用技巧
    java中线程的基本方法的熟练使用是精通多线程编程的必经之路,线程相关的基本方法有wait,notify,notifyAll,sleep,join,yield等,本文浅要的介绍一下它们的使用方式。线程的状态图java将操作系统中的就绪和运行...
    99+
    2023-05-31
    java 线程 使用
  • shell脚本编程if语句的使用方法
    本篇内容主要讲解“shell脚本编程if语句的使用方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“shell脚本编程if语句的使用方法”吧!我不是研究linux下的东西的,所以这里只对shel...
    99+
    2023-06-09
  • 使用 Golang 探讨基于方法的编程思维
    面向方法的编程思维是一种将程序设计从对象的角度转向方法的使用的编程范式。在这种编程思维下,重点不再是对象的属性和数据,而是对象的方法和行为。这种方法可以使代码更加模块化、可复用和可维护...
    99+
    2024-02-26
  • 利用C#编写一个Windows服务程序的方法详解
    1.添加引用Windows服务(.NET Framework) 2.输入项目名称,选择安装位置,,选择安装框架版本;创建。 3.找到MyService.cs ,右击‘...
    99+
    2023-03-14
    C#编写Windows服务程序 C# Windows服务程序 C# Windows服务
  • Node.js中同步和异步编程的区别及使用方法
    目录一、进程和线程二、同步和异步同步阻塞异步问题一、进程和线程 代码编写完毕在编译的过程中计算机的内存中会开辟一个空间来存储代码,这个空间就相当于是进程,可以将进程类比于工厂的厂房,...
    99+
    2023-05-18
    Node.js中同步和异步 Node.js 同步 Node.js 异步
  • java中多线程与线程池的基本使用方法
    目录前言继承Thread 实现Runnale接口Callable线程池常见的4种线程池。总结前言 在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器...
    99+
    2024-04-02
  • 如何使用Java编写高效的容器算法打包程序?
    Java是一种功能强大的编程语言,它的容器类提供了许多强大的算法,可以帮助开发人员更高效地编写程序。本文将介绍如何使用Java编写高效的容器算法打包程序。 一、使用ArrayList容器实现打包程序 ArrayList是Java中最常用的容...
    99+
    2023-11-08
    打包 编程算法 容器
  • 从算法到存储:使用 Go 和 Bash 编写高效的程序。
    从算法到存储:使用 Go 和 Bash 编写高效的程序 随着计算机科学的不断发展,我们的计算机技能和工具也在不断更新。在这个时代,我们需要编写高效的程序来处理海量的数据,同时还需要保证代码的可维护性和可读性。在本文中,我们将介绍如何使用 G...
    99+
    2023-11-05
    bash 编程算法 存储
  • 日志记录在go教程中的重要性:为什么使用shell比其他方式更好?
    日志记录在Go教程中的重要性:为什么使用Shell比其他方式更好? 在软件开发过程中,日志记录是一项不可或缺的任务。通过记录系统的行为和状态,我们可以更好地理解系统的运行情况,分析问题,并及时发现和解决潜在的问题。在Go语言中,日志记录也是...
    99+
    2023-06-22
    教程 日志 shell
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作