1、虽然这种用法和谷歌的自己的C+编程风格指南相悖,但由于你需要不停的使用V8定义的类型,所以目前为止的大多数node的扩展仍然使用了V8的命名空间。接下来,声明HelloWorld类。它继承自node:ObjectWrap类 ,这个类提供了几个如引用计数、在V8内部传递contex等的实用功能。一般来说,所有对象应该继承ObjectWrap:class HelloWorld: ObjectWrapprivate: int m_count;public:声明类之后,我们定义了一个静态成员函数,用来初始化对象并将其导入Node.js提供的target对象中。设个函数基本上是告诉Node.js和V8你
2、的类是如何创建的,和它将包含什么方法:static Persistent s_ct; static void Init(Handle target) HandleScope scope; Local t = FunctionTemplate:New(New); s_ct = PersistentInstanceTemplate()-SetInternalFieldCount(1);SetClassName(String:NewSymbol(HelloWorld); NODE_SET_PROTOTYPE_METHOD(s_ct, hello, Hello); target-Set(String:
3、),GetFunction(); 在上面这个函数中target参数将是模块对象,即你的扩展将要载入的地方。(译著:这个函数将你的对象及其方法连接到这个模块对象,以便外界可以访问)首先我们为New方法创建一个FunctionTemplate,将于稍后解释。我们还为该对象添加一个内部字段,并命名为HelloWorld。然后使用NODE_SET_PROTOTYPE_METHOD宏将hello方法绑定到该对象。最后,一旦我们建立好这个函数模板后,将他分配给target对象的HelloWorld属性,将类暴露给用户。接下来的部分是一个标准的C+构造函数:HelloWorld() : m_count(0)
4、 HelloWorld()接下来,在:New 方法中V8引擎将调用这个简单的C+构造函数:static Handle New(const Arguments& args) HelloWorld* hw = new HelloWorld(); hw-Wrap(args.This(); return args.This();此段代码相当于上面Javascript代码中使用的构造函数。它调用new HelloWorld 创造了一个普通的C+对象,然后调用从ObjectWrap继承的Wrap方法, 它将一个C+HelloWorld类的引用保存到args.This()的值中。在包装完成后返回args.T
5、his(),整个函数的行为和javascript中的new运算符类似,返回this指向的对象。现在我们已经建立了对象,下面介绍在Init函数中被绑定到hello的函数: Hello(const Arguments& HelloWorld* hw = ObjectWrap:Unwrap(args.This();m_count+;String result = String:New( return scope.Close(result);函数中首先使用ObjectWrap模板的方法提取出指向HelloWorld类的指针,然后和javascript版本的HelloWorld一样递增计数器。我们新建一
6、个内容为“HelloWorld”的v8字符串对象,然后在关闭本地作用域的时候返回这个字符串。上面的代码实际上只是针对v8的接口,最终我们还需要让Node.js知道如何动态加载我们的代码。为了使Node.js的扩展可以在执行时从动态链接库加载,需要有一个dlsym函数可以识别的符号,所以执行编写如下代码:extern C static void init (Handle在Hello函数的入口处 ,我们使用宏从参数列表的第一个位置获取回调函数,在下一节中将详细介绍。然后,我们使用相同的Unwarp方法提取指向类对象的指针。 hello_baton_t *baton = new hello_bato
7、n_t(); baton-hw = hw;increment_by = 2;sleep_for = 1;cb = PersistentNew(cb);这里我们创建一个baton结构,并将各种参数保存在里面。请注意,我们为回调函数创建了一个永久引用,因为我们想要在超出当前函数作用域的地方使用它。如果不这么做,在本函数结束后将无法再调用回调函数。Ref(); eio_custom(EIO_Hello, EIO_PRI_DEFAULT, EIO_AfterHello, baton); ev_ref(EV_DEFAULT_UC); return Undefined();如下代码是真正的重点。首先,我们
8、增加HelloWorld对象的引用计数,这样在其他线程执行的时候他就不会被回收。函数eio_custom接受两个函数指针作为参数。EIO_Hello函数将在线程池中执行,然后EIO_AfterHello函数将回到在“主线程”中执行。我们的baton结构也被传递进各函数,这些函数可以使用baton结构中的数据完成相关的操作。同时,我们也增加event loop的引用。这很重要,因为如果event loop无事可做,Node.js就会退出。最终,函数返回Undefined,因为真正的工作将在其他线程中完成。static int EIO_Hello(eio_req *req) hello_baton
9、_t *baton = static_cast(req-data); sleep(baton-sleep_for);hw-m_count += baton-increment_by; return 0;这个回调函数将在libeio管理的线程中执行。首先,解析出baton结构,这样可以访问之前设置的各种参数。然后sheep baton-sleep_for秒,这么做是安全的,因为这个函数运行在独立的线程中并不会阻塞主线程中javascript的执行。然后我们的增计数器,在实际的系统中,这些操作通常需要使用Lock/Mutex进行同步。当上述方法返回后,libeio将会通知主线程它需要在主线成上执行
10、代码,此时EIO_AfterHello将会被调用。static int EIO_AfterHello(eio_req *req) ev_unref(EV_DEFAULT_UC);Unref();进度此函数时,我们提取出baton结构,删除事件循环的引用,并减少HelloWorld对象的引用。 argv1; argv0 = String: TryCatch try_catch;cb-Call(Context:GetCurrent()-Global(), 1, argv); if (try_catch.HasCaught() FatalException(try_catch);新建要传递给回调函数
11、的字符串参数,并放入字符串数组中。然后我们调用回调传递一个参数,并检测可能抛出的异常。cb.Dispose(); delete baton;在执行过回调之后,应该销毁持久引用,然后删除之前创建的baton结构。最后,你可以使用如下形式在Javascript中使用该模块:var helloeio = require(./helloworld_eiohi = new helloeio.HelloWorldEio();hi.hello(function(data) console.log(data););参数传递与解析除了HelloWorld之外,你还需要理解最后一个问题:参数的处理。在helloW
12、orld EIO例子中,我们使用一个REQ_FUN_ARG宏,然我们看看这个宏到底都做些什么。#define REQ_FUN_ARG(I, VAR) if (args.Length() IsFunction() return ThrowException(Exception:TypeError( String:Argument #I must be a function); VAR = Local/ A nonsensical node.js programvar Dummy = require(var kenny = new Dummy();var dinner = kenny.cookin
13、g(fried_chix);dinner.on(, function(chicken) / eat up!所以基本上,node.js执行脚本,然后等待cooked事件被触发,并在事件触发之后调用回调函数并传递返回的参数。还有什么要注意的值得注意的是,例子中使用的“子类”和事件有一些极端(a bit of an overkill)。EventEmitter每次只触发一个事件(EventEmitter for things that only fire one event once)。如果只创造少数几个实例,可以将方法直接加入到实例本身,如果要触发底层事件,可能实用异步函数会更好一些。关于events.EventEmitter,你还需注意一个特别的事件:error。任何错误发生时此事件都会触发,并且当没有监听程序监听这个事件时,node将会抛出异常并结束应用程序。(感谢Tim指出这一点)
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1