- 浏览: 97227 次
- 性别:
- 来自: 临沂
文章分类
- 全部博客 (125)
- spring (2)
- java (6)
- jquery (0)
- android (0)
- window (1)
- 数据库 (0)
- 项目管理 (1)
- maven (0)
- english (0)
- ext (0)
- javascript and html (2)
- hibernate (1)
- p6spy (0)
- shiro (0)
- fusionchart (0)
- FileUtils (0)
- struts2 (0)
- ireport (0)
- webservice (0)
- stripes (0)
- jsp (1)
- it综合 (1)
- linux (1)
- 工作流 (0)
- activiti (0)
- poi (0)
- nosql (0)
- mongodb (0)
- lucene (0)
- nodejs (10)
- eclipse (2)
- objective-c (1)
最新评论
本文是对nodejs0.8.9版本的api开发手册解读.nodejs网址
因本人没有c++编译环境,故下面代码没有做测试.
插件(Addons)
插件是动态被连接到共享的对象.他们可以提供一种c和c++类库结合的能力.Api(目前)还是想当复杂,包括几个类库的知识:
- V8 javascript 引擎,一个c++类库.用于和javascript连接接口:创建对象,调用方法,等等.在弄的源码目录树中的dpes/v8/include/v8.h文件中做了说明,也可以在线查看.
- libuv,c的事件循环库.在任何时间,一个需要等待一个文件描述符变成可读的事件,等待一个定时器,或者等待一个信号来接受都需要使用libux.就是这样,如果你需要i/o操作,你就需要使用libux.
- internal node libraries,node核心库,大部分很重要的库都是node::ObjectWrap的类,方便有调用.
- others.可以在deps下查看其他可见的库.
node总是静态的编译所有的依赖到可执行文件.当编译你的模块时,你不需要担心的连接到任何地方的libs.
Hello World
作为开始,让我们来制作一个小插件,下面的代码是和c++等价的js代码:
exports.hello = function() { return 'world'; };
首先我们来创建一个hello.cc:
#include <node.h>
#include <v8.h>
using namespace v8;
Handle<Value> Method(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("world"));
}
void init(Handle<Object> target) {
target->Set(String::NewSymbol("hello"),
FunctionTemplate::New(Method)->GetFunction());
}
NODE_MODULE(hello, init)
注意,所有的模块插件必须导出一个初始化的方法:
void Initialize (Handle<Object> target);
NODE_MODULE(module_name, Initialize)
因为NODE_MODULE不是一个函数,所以它后面没有分号.(参见hello.h).
module_name必须要匹配除去node后缀的文件名.
源代码需要被编译成hello.node,二进制插件.为了这么做我们创建一个叫做binding.gyp的文件,它描述了如何把你的模块编译称类似json格式的配置信息.这个文件将会被node-gyp编译成:
{
"targets": [
{
"target_name": "hello",
"sources": [ "hello.cc" ]
}
]
}
下一步是生成适合当前平台的build文件,用node-gyp configure来做.
现在你会build目录下发现一个makefile(在unix平台上)或者一个vcxproj文件(在windows上).下一步调用node-gyp build 命令.
现在你已经有了编译后的.node捆绑文件.这些捆绑文件被放在build/release目录下.
现在你就可以在node项目hello.js中通过require指向刚刚创建的hello.nod二进制模块插件:
var addon = require('./build/Release/hello');
console.log(addon.hello()); // 'world'
更深入的了解可以参考下面的patterns部分,或者https://github.com/arturadib/node-qt提供了一个产品例子.
插件模型(Addon patterns)
下面的一些插件模型,可以在你开始学习插件模型时提供帮助.可以通过查阅在线的v8 reference来获取关于多样的v8调用的相关帮助,从v8的Embedder's
Guide中获取对一些概念的使用例如:handles,scopes,function,templates等的解释说明.
为了使用这些例子,你需要使用node-gyp去编译他们,创建下面的binding.gyp文件:
{
"targets": [
{
"target_name": "addon",
"sources": [ "addon.cc" ]
}
]
}
在不止一个.cc文件的情况下,只需要简单的添加文件名称到source变量数组中即可,例如:
"sources": ["addon.cc", "myexample.cc"]
现在你的binding.gyp已经就绪,你可以配置和创建插件了:
$ node-gyp configure build
方法参数(Function arguments)
下面的模型阐述了如何从javascript函数调用中读取参数和返回一个结果.这是大体内容,而亲仅仅只是需要addon.cc而已:
#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> Add(const Arguments& args) {
HandleScope scope;
if (args.Length() < 2) {
ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
return scope.Close(Undefined());
}
if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
ThrowException(Exception::TypeError(String::New("Wrong arguments")));
return scope.Close(Undefined());
}
Local<Number> num = Number::New(args[0]->NumberValue() +
args[1]->NumberValue());
return scope.Close(num);
}
void Init(Handle<Object> target) {
target->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
}
NODE_MODULE(addon, Init)
你可以使用下面的代码片段来测试它:
var addon = require('./build/Release/addon');
console.log( 'This should be eight:', addon.add(3,5) );
回调(Callbacks)
在这里你可以把一个javascript函数传递一个c++函数,并且执行他们.这是addon.cc:
#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> RunCallback(const Arguments& args) {
HandleScope scope;
Local<Function> cb = Local<Function>::Cast(args[0]);
const unsigned argc = 1;
Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) };
cb->Call(Context::GetCurrent()->Global(), argc, argv);
return scope.Close(Undefined());
}
void Init(Handle<Object> target) {
target->Set(String::NewSymbol("runCallback"),
FunctionTemplate::New(RunCallback)->GetFunction());
}
NODE_MODULE(addon, Init)
运行下面的javascript代码片段来测试它:
var addon = require('./build/Release/addon');
addon.runCallback(function(msg){
console.log(msg); // 'hello world'
});
对象工厂(Object factory)
这个模型阐述了如何创建并且返回一个包裹着c++函数的javascript函数:
#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> MyFunction(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("hello world"));
}
Handle<Value> CreateFunction(const Arguments& args) {
HandleScope scope;
Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);
Local<Function> fn = tpl->GetFunction();
fn->SetName(String::NewSymbol("theFunction")); // omit this to make it anonymous
return scope.Close(fn);
}
void Init(Handle<Object> target) {
target->Set(String::NewSymbol("createFunction"),
FunctionTemplate::New(CreateFunction)->GetFunction());
}
NODE_MODULE(addon, Init)
测试:
var addon = require('./build/Release/addon');
var fn = addon.createFunction();
console.log(fn()); // 'hello world'
包裹c++对象(Wrapping C++ Objects)
这里我们将为一个c++对象或者类MyObject创建一个包裹器,可以在javascript中通过new操作符可以实例化的那种.首先我们要准备主模块addon.cc:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
void InitAll(Handle<Object> target) {
MyObject::Init(target);
}
NODE_MODULE(addon, InitAll)
然后在myobject.h中确保你的包裹器继承自:node::ObjectWrap:
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <node.h>
class MyObject : public node::ObjectWrap {
public:
static void Init(v8::Handle<v8::Object> target);
private:
MyObject();
~MyObject();
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
double counter_;
};
#endif
然后在addon.cc中实现那些你想暴露的各种各样的方法.这里我们通过把plusone方法添加到构造方法的prototype中来暴漏它:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
MyObject::MyObject() {};
MyObject::~MyObject() {};
void MyObject::Init(Handle<Object> target) {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction());
target->Set(String::NewSymbol("MyObject"), constructor);
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
MyObject* obj = new MyObject();
obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
obj->Wrap(args.This());
return args.This();
}
Handle<Value> MyObject::PlusOne(const Arguments& args) {
HandleScope scope;
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->counter_ += 1;
return scope.Close(Number::New(obj->counter_));
}
测试:
var addon = require('./build/Release/addon');
var obj = new addon.MyObject(10);
console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13
包裹对象的工厂(Factory of Wrapped Objects)
当你们想要在javascript中不使用new操作符实例化的情况下可以创建本地对象,这节内容是有用的.例如:
var obj = addon.createObject();
// instead of:
// var obj = new addon.Object();
让我们在addon.cc中注册createObject方法:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
HandleScope scope;
return scope.Close(MyObject::NewInstance(args));
}
void InitAll(Handle<Object> target) {
MyObject::Init();
target->Set(String::NewSymbol("createObject"),
FunctionTemplate::New(CreateObject)->GetFunction());
}
NODE_MODULE(addon, InitAll)
在myobject.h中现在我们引入了可以帮助实例化对象的静态方法NewInstance(也就是在javascript中干new的活):
#define BUILDING_NODE_EXTENSION
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <node.h>
class MyObject : public node::ObjectWrap {
public:
static void Init();
static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
private:
MyObject();
~MyObject();
static v8::Persistent<v8::Function> constructor;
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
double counter_;
};
#endif
在myobject.cc中的实现和上面代码是很类似的:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
MyObject::MyObject() {};
MyObject::~MyObject() {};
Persistent<Function> MyObject::constructor;
void MyObject::Init() {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
MyObject* obj = new MyObject();
obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
obj->Wrap(args.This());
return args.This();
}
Handle<Value> MyObject::NewInstance(const Arguments& args) {
HandleScope scope;
const unsigned argc = 1;
Handle<Value> argv[argc] = { args[0] };
Local<Object> instance = constructor->NewInstance(argc, argv);
return scope.Close(instance);
}
Handle<Value> MyObject::PlusOne(const Arguments& args) {
HandleScope scope;
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->counter_ += 1;
return scope.Close(Number::New(obj->counter_));
}
测试:
var addon = require('./build/Release/addon');
var obj = addon.createObject(10);
console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13
var obj2 = addon.createObject(20);
console.log( obj2.plusOne() ); // 21
console.log( obj2.plusOne() ); // 22
console.log( obj2.plusOne() ); // 23
任意传递包裹的对象(Passing Wrapped Objects around)
除了包裹和返回c++对象之外,你可以通过node的node::ObjectWrap::Unwrap帮助函数来传递他们.在下面的addon.cc中我们引进了一个接受两个myobject作为参数的add()方法:
#define BUILDING_NODE_EXTENSION #include <node.h> #include "myobject.h" using namespace v8; Handle<Value> CreateObject(const Arguments& args) { HandleScope scope; return scope.Close(MyObject::NewInstance(args)); } Handle<Value> Add(const Arguments& args) { HandleScope scope; MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>( args[0]->ToObject()); MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>( args[1]->ToObject()); double sum = obj1->Val() + obj2->Val(); return scope.Close(Number::New(sum)); } void InitAll(Handle<Object> target) { MyObject::Init(); target->Set(String::NewSymbol("createObject"), FunctionTemplate::New(CreateObject)->GetFunction()); target->Set(String::NewSymbol("add"), FunctionTemplate::New(Add)->GetFunction()); } NODE_MODULE(addon, InitAll)为了让事情变的更有趣,我们在myobject.h中引入了一个公共方法,这样一来我们可以在unwrapping之后探测私有变量:
#define BUILDING_NODE_EXTENSION #ifndef MYOBJECT_H #define MYOBJECT_H #include <node.h> class MyObject : public node::ObjectWrap { public: static void Init(); static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args); double Val() const { return val_; } private: MyObject(); ~MyObject(); static v8::Persistent<v8::Function> constructor; static v8::Handle<v8::Value> New(const v8::Arguments& args); double val_; }; #endifmyobject.cc的实现还是和上面的很类似:
#define BUILDING_NODE_EXTENSION #include <node.h> #include "myobject.h" using namespace v8; MyObject::MyObject() {}; MyObject::~MyObject() {}; Persistent<Function> MyObject::constructor; void MyObject::Init() { // Prepare constructor template Local<FunctionTemplate> tpl = FunctionTemplate::New(New); tpl->SetClassName(String::NewSymbol("MyObject")); tpl->InstanceTemplate()->SetInternalFieldCount(1); constructor = Persistent<Function>::New(tpl->GetFunction()); } Handle<Value> MyObject::New(const Arguments& args) { HandleScope scope; MyObject* obj = new MyObject(); obj->val_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue(); obj->Wrap(args.This()); return args.This(); } Handle<Value> MyObject::NewInstance(const Arguments& args) { HandleScope scope; const unsigned argc = 1; Handle<Value> argv[argc] = { args[0] }; Local<Object> instance = constructor->NewInstance(argc, argv); return scope.Close(instance); }测试:
var addon = require('./build/Release/addon'); var obj1 = addon.createObject(10); var obj2 = addon.createObject(20); var result = addon.add(obj1, obj2); console.log(result); // 30
发表评论
-
一起读nodejs(八)----域(domain)
2012-09-19 09:13 860本文是对nodejs0.8.9版本的api开发手册解读.n ... -
一起读nodejs(九)----缓存类(Buffer)
2012-09-21 09:20 3354本文是对nodejs0.8.9版本的api开发手 ... -
一起读nodejs(一)----概览和全局对象(Synopsis &Global Objects)
2012-09-03 09:02 745本文是对nodejs0.8.9版本的api开发手册解读.nod ... -
一起读nodejs(二)----控制台和定时器(console &Timer)
2012-09-06 09:30 918本文是对nodejs0.8.9版本的api开发手册解读.nod ... -
一起读nodejs(三)----模块(Modules)
2012-09-07 08:37 1154本文是对nodejs0.8.9版本的api开发手册解读.n ... -
一起读nodejs(五)----进程(process)
2012-09-12 08:51 1690本文是对nodejs0.8.9 ... -
nodejs version 0.8.9稳定版更新日志
2012-09-12 09:46 12052012.09.11,0.8.9版本(稳定版) ... -
一起读nodejs(六)----工具类(Utilties)
2012-09-14 08:51 2649本文是对nodejs0.8.9版 ... -
一起读nodejs(七)----事件(Events)
2012-09-17 08:46 1115本文是对nodejs0.8.9版本的api开发手册解读.n ...
相关推荐
Node.js API 中文文档 Node.js 是一个基于 Chrome V8 JavaScript 引擎的 JavaScript 运行环境,它...C/C++ Addons * C/C++ 插件模块:提供了 C/C++ 插件的实现 * Hello world 插件:提供了一个简单的 C/C++ 插件示例
NodeJs Addons是一个存储库,它显示了通过 v8 api 导出的不同 JavaScript 对象。 如果有任何问题让您花费了大量时间来弄清楚 - 或者您想增加一些复杂性,那么请随意破解。 安装 npm install node-addons 然后希望...
【Node.js Addons 插件】是Node.js平台上的扩展机制,允许开发者使用C++编写高性能的代码并与JavaScript进行交互。这些插件本质上是动态链接库,通过Node.js的API与V8 JavaScript引擎以及libuv事件循环库进行绑定,...
【Node.js Addons 插件开发详解】 Node.js Addons 是一种使用 C 或 C++ 编写的动态链接库,它们可以与 Node.js 的 V8 JavaScript 引擎和 libuv 事件循环库紧密集成,实现高性能的原生扩展功能。Addons 提供了一种...
Node.js插件(可以在找到完整的仓库)有时您想直接从节点应用程序使用现有的c ++代码。 您可以使用Node.js插件, 和库来实现。C ++代码// hello.cc# include < node>namespace demo { using v8::...
NodeJS C ++插件 :flexed_biceps: 该存储库包含NodeJS的C ++插件示例。 :bookmark: 描述主要思想是提供有关如何使用C ++为NodeJS创建插件的示例和提示的文档。 C和C ++是我的第一门编程语言,我从中学习了基础知识,...
#### Addons(扩展插件) 扩展插件是指那些用 C/C++ 编写的模块,可以用来增强 Node.js 的功能。 - **安装扩展插件**:通常使用 npm 安装。 - **编写扩展插件**:需要熟悉 C/C++ 和 Node.js 的 API。 #### ...
使用C ++和N-API(node-addon-api)编写NodeJS插件的初学者指南博客链接: 运行示例: git clone https://github.com/master-atul/blog-addons-example npm install npm run build //这几乎是不需要的。 但以防万一...
### Node.js C++ 插件学习指南 #### 一、Node.js C++ 插件概述 Node.js C++ 插件是一种特殊的模块,它由 C++ 编写而成,并能够被 Node.js 通过 `require()` 函数加载。这类插件可以提供高性能的原生功能,用于增强...
@ pepperi-addons-导入/导出ATD插件 用于使用客户端的angular应用程序和用于服务器端的typescript nodejs应用程序创建Pepperi附加组件的模板 在vscode中调试服务器端 用于为插件创建所有已编译文件的构建脚本 一个...
主要用来解决没有营业执照,想使用微信和支付宝收款,收款的逻辑在/api/addons/pay.js文件里,不需要后台等功能的同学可以根据此文件单独写自己的功能,可我不喜欢nodeJS啊,那你可以使用你喜欢的任何语言进行开发;...
描述中提到,这个插件已经移到了monorepo(多模块单个仓库)管理。Monorepo策略是将所有相关项目代码存储在一个单一的Git仓库中,便于代码共享、版本控制和协同工作。此外,该存储库已经被存档,这意味着它可能不再...
标题中的"my-node-addon.zip"很可能包含了一个这样的原生模块示例,用于展示如何通过C++编写Node.js插件,同时实现了普通函数和回调函数的交互。这种技术对于优化I/O密集型或计算密集型任务非常有用,因为它允许...
kylinjs kylinjs 基于 koa 的 nodejs服务端框架 整合了如下常用模块: http请求、 后端模板nunjucks、模板helpers 路由routes、 路由过滤器filter、 日志模块logger、 插件系统addons 使用方法
故事书设置 在里面 cd web npx sb init 跑 npm run storybook 附加组件 npm install --save-dev storybook-addon-designs 在.storybook/main.js注册插件 ... addons : [ 'storybook-addon-designs' ] , }