- 浏览: 55951 次
最新评论
Addons是动态链接共享对象。它们能提供和c及c++库的粘合。API(当前)是比较复杂的,包含了一些库的知识:
●V8 JavaScript,一个C++库。被用来作为Javascript接口:建立对象,调用方法等等。在v8.h头文件中有说明文档(在Node源树中的deps/v8/include/v8.h),它也可在线查看。
●libuv,C事件loop库。任何时候谁需要等待一个文件描述符变成可读,等待一个计时器,或者等待一个信号来接收什么将需要和libuv接口。换言之,如果你执行任何I/O,libuv将需要被使用到。
●内部Node库。Most importantly is the node::ObjectWrap class which you will likely want to derive from.
●其他。 Look in deps/ for what else is available.
Node静态编译它的所有依赖到可执行文件。当编译你的模块,你不需要担心链接到任何这些库。
Hello world
让我们建立一简单的Addon,它是一个C++,等价于下面的Javascript代码:
首先我们建立一个文件hello.cc:
注意所有的Node addons必须导出一个初始化函数:
在NODE_MODULE后没有分号因为它不是一个函数(请看node.h)。
module_name 需要对应最后的二进制文件名(去掉node后缀)。
源代码需要构建到hello.node中,二进制Addon。为了做到这个我们建立一个名为binding.gyp文件,它以类似JSON的格式描述了建立你的模块的配置。这个文件通过node-gyp编译。
下一步是为当前平台生成适当的项目构建文件。为此使用node-gypconfigure。
现在你将会在build/ directory目录下有一个Makefile(在Unix平台上)或者vcxproj文件(在Windows平台上)。下一步调用node-gyp build命令。
现在你有你的编译过的.node bindings文件了!编译过的bindings在build/Release/里。
你现在能在Node项目hello.js中使用字节addon了,通过将require指向刚建立的hello.node模块:
更多的信息请参看下面的模式或https://github.com/arturadib/node-qt 中一个产品项目。
Addon 模式
下面是一些addon模式来帮助你开始。请参考在线v8参考帮助中的各种v8调用,和v8的Embedder指南对使用的几个概念的解释,比如handles,scopes,function templates等待。
为了去使用这些示例你需要使用node-gyp编译它们。建立如下的binding.gyp文件:
在某些情况下有不止一个.cc文件,只需添加文件的名字到来源数组,例如:
现在你的binding.gyp准备就绪,你能配置和组件addon:
函数参数
以下模式演示了如何从JavaScript函数调用读取参数并返回一个结果。这是主要的,和唯一必要的源代码addon.cc:
你能使用下面的Javascript片段来测试它:
回调
你能传递Javascript函数到C++函数中并在那里执行它们。下面是addon.cc:
使用下面的Javascript片段进行测试:
对象工厂
通过这个addon.cc模式,你能在C++函数中建立和返回新对象,它返回的新对象有msg属性,它echo传递到createObject()的字符串:
在Javascript中进行测试:
函数工厂
这种模式演示了如何创建并返回一个包装了一个c++函数的JavaScript函数:
如下测试:
Wrapping C++对象
这里我们将为 C++ object/class MyObject 建立一个wrapper,该object可以通过新的操作符在JavaScript中实例化。首先准备主要的模块addon.css:
然后在myobject.h 中从node::ObjectWrap继承你的包装器:
然后在myobject.cc中实现你想要公开的各种方法。这里我们公开方法plugOne,则添加它到constructor's prototype:
如下测试:
Factory of wrapped objects
这是有用的,例如当你希望能够创建本地对象又不在Javascript中使用new操作符显式地实例化它们。
让我们在addon.cc中注册我们的createObject 函数:
在myobject.h中我们现在介绍静态方法NewInstance,它负责对象的实例化(也就是它做了JavaScript中的new的工作):
The implementation is similar to the above in myobject.cc:
如下测试:
Passing wrapped objects around
除了包装并返回c++对象,你能通过使用Node's node::ObjectWrap::Unwrap helper function展开它们来pass them around。在下面的addon.cc我们引入一个函数add(),它可以接纳两个MyObject对象:
为了使事情有趣的我们在myobject.h中引入一个公共方法,这样我们就可以在对象展开后探测私有值:
myobject.cc的实现和前面类似:
如下测试:
●V8 JavaScript,一个C++库。被用来作为Javascript接口:建立对象,调用方法等等。在v8.h头文件中有说明文档(在Node源树中的deps/v8/include/v8.h),它也可在线查看。
●libuv,C事件loop库。任何时候谁需要等待一个文件描述符变成可读,等待一个计时器,或者等待一个信号来接收什么将需要和libuv接口。换言之,如果你执行任何I/O,libuv将需要被使用到。
●内部Node库。Most importantly is the node::ObjectWrap class which you will likely want to derive from.
●其他。 Look in deps/ for what else is available.
Node静态编译它的所有依赖到可执行文件。当编译你的模块,你不需要担心链接到任何这些库。
Hello world
让我们建立一简单的Addon,它是一个C++,等价于下面的Javascript代码:
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)
注意所有的Node addons必须导出一个初始化函数:
void Initialize (Handle<Object> target); NODE_MODULE(module_name, Initialize)
在NODE_MODULE后没有分号因为它不是一个函数(请看node.h)。
module_name 需要对应最后的二进制文件名(去掉node后缀)。
源代码需要构建到hello.node中,二进制Addon。为了做到这个我们建立一个名为binding.gyp文件,它以类似JSON的格式描述了建立你的模块的配置。这个文件通过node-gyp编译。
{ "targets": [ { "target_name": "hello", "sources": [ "hello.cc" ] } ] }
下一步是为当前平台生成适当的项目构建文件。为此使用node-gypconfigure。
现在你将会在build/ directory目录下有一个Makefile(在Unix平台上)或者vcxproj文件(在Windows平台上)。下一步调用node-gyp build命令。
现在你有你的编译过的.node bindings文件了!编译过的bindings在build/Release/里。
你现在能在Node项目hello.js中使用字节addon了,通过将require指向刚建立的hello.node模块:
var addon = require('./build/Release/hello'); console.log(addon.hello()); // 'world'
更多的信息请参看下面的模式或https://github.com/arturadib/node-qt 中一个产品项目。
Addon 模式
下面是一些addon模式来帮助你开始。请参考在线v8参考帮助中的各种v8调用,和v8的Embedder指南对使用的几个概念的解释,比如handles,scopes,function templates等待。
为了去使用这些示例你需要使用node-gyp编译它们。建立如下的binding.gyp文件:
{ "targets": [ { "target_name": "addon", "sources": [ "addon.cc" ] } ] }
在某些情况下有不止一个.cc文件,只需添加文件的名字到来源数组,例如:
"sources": ["addon.cc", "myexample.cc"]
现在你的binding.gyp准备就绪,你能配置和组件addon:
$ node-gyp configure build
函数参数
以下模式演示了如何从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)
你能使用下面的Javascript片段来测试它:
var addon = require('./build/Release/addon'); console.log( 'This should be eight:', addon.add(3,5) );
回调
你能传递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' });
对象工厂
通过这个addon.cc模式,你能在C++函数中建立和返回新对象,它返回的新对象有msg属性,它echo传递到createObject()的字符串:
#define BUILDING_NODE_EXTENSION #include <node.h> using namespace v8; Handle<Value> CreateObject(const Arguments& args) { HandleScope scope; Local<Object> obj = Object::New(); obj->Set(String::NewSymbol("msg"), args[0]->ToString()); return scope.Close(obj); } void Init(Handle<Object> target) { target->Set(String::NewSymbol("createObject"), FunctionTemplate::New(CreateObject)->GetFunction()); } NODE_MODULE(addon, Init)
在Javascript中进行测试:
var addon = require('./build/Release/addon'); var obj1 = addon.createObject('hello'); var obj2 = addon.createObject('world'); console.log(obj1.msg+' '+obj2.msg); // 'hello world'
函数工厂
这种模式演示了如何创建并返回一个包装了一个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'
Wrapping C++对象
这里我们将为 C++ object/class MyObject 建立一个wrapper,该object可以通过新的操作符在JavaScript中实例化。首先准备主要的模块addon.css:
#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
然后在myobject.cc中实现你想要公开的各种方法。这里我们公开方法plugOne,则添加它到constructor's 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
The implementation is similar to the above in 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's node::ObjectWrap::Unwrap helper function展开它们来pass them around。在下面的addon.cc我们引入一个函数add(),它可以接纳两个MyObject对象:
#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中引入一个公共方法,这样我们就可以在对象展开后探测私有值:
#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_; }; #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); 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
发表评论
文章已被作者锁定,不允许评论。
-
三次样条曲线
2014-04-11 17:33 1866原文地址: http://www.math ... -
APPLE PUBLIC SOURCE LICENSE (APSL)
2013-05-23 13:47 0原文地址:http://www.publicsource.ap ... -
翻译的一些说明
2013-03-07 14:48 0翻译的一些说明: 1,对于一些专有名词如speex,api不过 ... -
libuv介绍--多线程
2013-05-23 10:59 13655原文:http://nikhilm.github.com/uv ... -
ALSA driver 安装指南(中文版)
2012-12-29 11:28 0ALSA 驱动替代了OSS/Free驱动。从版本0.4.0开始 ... -
ALSA driver 安装指南(英文版)
2012-12-28 14:30 0Advanced Linux Sound Architectu ... -
8.4和Apache Geronimo集成
2013-04-16 20:01 1548Apache Geronimo应用服务器是在应用服务器许多方面 ... -
8.3和Jetty集成
2013-04-16 19:58 1121Jetty web container已经存在了很长时间并使可 ... -
8.2和Apache Tomcat集成
2013-03-11 21:54 1499Apache Tomcat是可论证的当今使用最广的可用的Jav ... -
8.1web应用示例
2013-03-11 21:54 11158.1web应用示例 为了在本章中演示集成示例,一个web应用 ... -
8.0将ActiveMQ集成到应用服务器
2013-03-11 21:54 957本章包括下面内容: ■ ... -
7.5小结
2013-03-11 21:53 627在本章中,你已经看到了ActiveMQ如何能被看做不仅是一个独 ... -
7.4使用Spring编写JMS客户端
2013-03-11 21:53 1481ActiveMQ使用Spring框架来ease client- ... -
7.3实现request/reply with JMS
2012-12-07 16:12 1482如前面章节中描述的,m ... -
7.2使用Spring嵌入ActiveMQ
2012-12-06 15:01 1677ActiveMQ is developed with Spri ... -
7.1使用Java嵌入ActiveMQ
2012-12-05 15:59 2003虽然今天的大多数开发者使用一个框架编写他们的应用,但是用最简单 ... -
7.0建立带ActiveMQ的Java程序
2012-12-05 13:47 1083本章包括: ■在Java应用程序中嵌入ActiveMQ ■使用 ... -
6.5总结
2012-12-05 11:33 725在这一章中,ActiveMQ被从无身份验证no-authent ... -
6.4基于证书的安全
2012-12-05 11:10 1455在本章前面部分,我们描述了ActiveMQ插件被用来验证客户端 ... -
ActiveMQ in action 1~4章
2012-11-27 16:25 848http://jfires.iteye.com/
相关推荐
标题中的"repository.xbmc-addons-chinese-2.0.0.zip"是一个针对KODI媒体中心的中文插件库的压缩包,版本号为2.0.0。这个压缩包包含了多款专为中国用户设计的KODI插件,旨在提升KODI在中文环境下的用户体验和功能...
而Fastadmin-addons,则是其专门为实现插件化开发设计的类库,它使得开发者能够轻松地创建、安装和管理各种插件,极大地提升了开发效率和系统的可扩展性。 在PHP世界里,插件是一种常见的模块化开发方式,它允许...
标题“repository.xbmc-addons-chinese-1.2.1.zip”揭示了这是一个与XBMC(Xbox Media Center)相关的软件资源包,版本号为1.2.1,并且是针对中文用户定制的。XBMC是一款开源的媒体中心软件,后来更名为Kodi,允许...
【标题】"org\vaadin\addons\dcharts-widget" 是一个与Vaadin框架相关的插件,主要用于在Web应用中提供数据图表的展示功能。Vaadin是一个流行的Java开发框架,用于构建用户界面,尤其是企业级的B2B应用程序。dcharts...
标题中的“repository.xbmc-addons-chinese-2.0.1.zip”是一个针对Kodi的中文插件库的压缩包,版本号为2.0.1。Kodi是一款开源的媒体中心软件,允许用户在各种设备上管理和播放多媒体内容,如视频、音乐和图片。这个...
【标题】"Ultimate_VC_Addons_WordPress_Ultimate_VC_Addons_wpaddon_Vc_php_源" 提供的是WordPress插件Ultimate VC Addons的PHP源代码,这是一款功能强大的Visual Composer扩展插件,用于增强WordPress网站的构建...
"Maxthon Browser Shopping Addons" 提供了一系列专为网购爱好者设计的插件和扩展,旨在优化用户的在线购物体验。这些插件通常包含了价格比较、优惠券查找、购物助手等功能,帮助用户在浏览商品时获取更多信息,从而...
《Beginning Lua with World of Warcraft Addons》作为一本专注于Lua语言与魔兽世界插件开发的教程,不仅适合初学者入门,也为有一定基础的开发者提供了深入学习和实践的机会。通过本书的学习,你将能够掌握一门强大...
而"前端开源库-redux-addons"则关注于Redux的扩展插件,这些插件旨在进一步提升Redux的功能和易用性。 Redux本身提供了一个中心化的状态容器,帮助开发者管理应用中的状态。然而,随着项目规模的增长,纯使用Redux...
《Onethink多图上传插件Addons:修复Flash Bug及增强功能解析》 Onethink是一款基于ThinkPHP框架的开源内容管理系统,它为开发者提供了丰富的功能和灵活的扩展性。在开发过程中,图片上传是常见的需求之一。针对这...
《Ultimate Addons for Visual Composer 3.16.10》是一款专为WPBakery Page Builder设计的强大扩展插件,旨在进一步丰富其内置功能,提供更多的设计元素和选项,帮助用户创建出更具视觉冲击力和专业感的网页内容。...
【标题】:“Firefox Common Addons” 【描述】:“Firefox Common Addons”指的是在Firefox浏览器上常用的扩展或插件。这些工具通常由开发者社区创建,旨在增强浏览器的功能,提高用户浏览体验,或者提供特定的...
资源来自pypi官网,解压后可用。 资源全名:tensorflow_addons-0.11.2-cp35-cp35m-win_amd64.whl
"ext-addons-7.6.0-trial" 是一个与ExtJS库相关的扩展包,它提供了7.6.0版本的附加组件。ExtJS是一个基于JavaScript的富客户端框架,广泛用于构建复杂的、数据驱动的Web应用程序。这个"trial"版可能意味着这是一个...
kodi中文插件最新2022 repository.xbmc-addons-chinese-2.0.0
"react-addons-create-fragment"是React早期版本的一个加载项,它提供了创建和管理多个子元素集合的能力,而不会在DOM中插入额外的节点。这个加载项在React 16版本之后被废弃,取而代之的是更现代和优化的API,如`...
org.vaadin.addons.dcharts-widget-0.10.0-dcharts-widget-0.10.0.jar
"react-addons-pure-render-mixin"是React的一个官方加载项,它提供了一个优化性能的策略,特别是在处理大型复杂应用时。 标题中的“react-addons-pure-render-mixin”是React的一个关键特性,用于帮助开发者实现更...
git remote add osbzr https://github.com/osbzr/gooderp_addons.git环境就准备好了把远程分支的合并到自己的分支1.把对方的代码拉到你本地。git fetch osbzr2.合并对方代码git merge osbzr/master3.最新的...
asterisk-addons-1.6.1-current.tar.gzasterisk-addons-1.6.1-current.tar.gzasterisk-addons-1.6.1-current.tar.gz