书籍作者:死月 | ISBN:9787121336423 |
书籍语言:简体中文 | 连载状态:全集 |
电子书格式:pdf,txt,epub,mobi,azw3 | 下载次数:8375 |
创建日期:2021-02-14 | 发布日期:2021-02-14 |
运行环境:PC/Windows/Linux/Mac/IOS/iPhone/iPad/Kindle/Android/安卓/平板 |
本书作者死月是 Node.js 核心贡献者(Node.js Core Collaborator)之一,CNode 社区版主之一,杭州 Node Party 组织者之一,曾任大搜车无线架构组 Node.js 团队负责人;浙江大学工程硕士,退役 OI、ACM 选手。
写这本书是我在2016 年底许下的愿望,希望在2018 年初完成一本技术专著。
我于2012 年加入Node.js 开发的大军, 现在也有幸成为Node.js 这个项目的Core Collaborator 之一。所以,我的意向就是为大家呈现一本Node.js 领域相关的书。但是现在市面上相关的书籍其实有很多了,我再写一本日常开发类的图书就显得有些多余。反而是在Node.js 的C++ 扩展开发方面,无论是在国内还是在国外,都是一块死角。就目前而言,国外市场我也只看到过一本电子书,并没有纸质图书出版,国内就更没有了。
Node.js 作为近几年新兴的一种编程运行时,托Chrome V8 引擎的福,在作为后端服务时有比较高的运行效率,在很多场景下对于我们的日常开发已经足够用了。不过,它也跟“PHP 提供了C 语言开发其原生扩展的方式”类似,为开发者开了一个使用C++ 开发Node.js 原生扩展的口子,让开发者进行项目开发时有了更多的选择。
实际上,在Node.js 的生态圈中,就有很多使用C++ 完成的包。如最近比较火的深度学习TensorFlow,其Node.js 版本的封装就是基于官方的C++ 源码完成的。我自己就是在日常开发中有一些相应的需求,使用纯粹的Node.js 来开发可能会使开发成本有点大,或者基本上做不到,又或者有性能上的要求。这时,我就会选择使用C++ 来实现它的一个扩展。在我写了一段时间C++ 扩展之后,想到可能在社区中有很多像我一样的人,苦于Node.js在底层操作时的一些局限性,如果他们也加入C++ 原生扩展开发阵营的话,兴许要再踩一遍我以前踩过的“坑”,找我之前找过的资料。因此,我就想把自己一路走来的经验分享给大家,让更多的人顺利地加入Node.js 的C++ 原生扩展开发的大军中。
我的Node.js 之路
我个人从小学开始接触静态网页的开发,直到高中开始参加信息学奥林匹克竞赛(Olympiad in Informatics, OI),才算正式踏入了编程之路。
在大学的时候我仍旧坚持参加大学生程序设计竞赛(ACM International Collegiate Programming Contest, ICPC),并且一直使用C++ 和PHP 进行开发。也是那时我打下了C++ 基础,这样才有机会现在完成这本书的写作工作。
我接触Node.js 其实并没有国内一些早期的布道者们早,相反还是有点迟的。在2012 年底,我决心学习Node.js,从而完成自己的一个创业项目。我当时的学习方法特别简单,买了一本BYVoid 的《Node.js 开发指南》,就算正式踏入了Node.js 领域。
在熟悉了Node.js 之后,我开始为Node.js 生态圈造轮子,如Toshihiko1、ThmclrX、Huaming3、mcnbt4 等。其实我个人认为,造轮子与写业务的一个不同点在于,造轮子可能会更容易遇到语言或是Node.js 运行时本身的“坑”。所以,这就促使我去深究Node.js 的文档,甚至源码。托我之前习得的C++ 基础的福,在阅读Node.js 源码时并不觉得特别艰难。
我在老东家花瓣网的时候,就已经初步开始了Node.js 的C++ 扩展开发。
后来我去了上一家就职的公司——大搜车,负责公司Node.js 团队的建设。当时我就开始更深入地挖掘Node.js 的一些内容了。甚至在2017 年年中的时候,我通过给Node.js 贡献源码,成为Node.js Core Collaborator 之一。我在为Node.js 贡献源码的时候,也为本书第3章和第6 章的写作打下了基础。
原生扩展的一些示例
在Node.js 早期的版本中, 运行子进程是纯异步的, 并没有像现在一样的各种spawnSync() 等函数。我当时写了一个命令行工具,在其所用到的一个帮助类中实现一个参数校验的函数必须同步返回一个布尔类型的值;然而我在这个校验函数中所需要做的事情就是判断当前系统的Git 版本。也就是说,我要通过子进程启动$ git -v,并得到它的结果看看版本是不是符合要求。当时Node.js 中运行子进程是异步的,达不到我的要求,所以我自己使用C++ 封装了一个原生扩展,使其能在Node.js 的事件循环中同步开启子进程并在其结束后获得它的终端输出——虽然Node.js 天生异步,但是在我的一个命令行工具中用同步形式执行这些内容也是没有问题的。
再比如,在大搜车的时候,项目用了阿里云的消息队列服务,而这款产品当时只有闭源的Java、C++ 等SDK,而C++ 的SDK 就只提供了几个动态链接库和一堆头文件,我们使用Node.js 的开发者就完全没法使用其服务。如果一定要用Node.js 进行开发,一个成本比较高的做法就是自己去逆向分析及研究消息队列服务的各种网络包的结构,自己解析,然后用Node.js 实现一个同样功能的库。然而这个方法基本不可行——尤其是在我们的项目高速迭代的时候。那么另一个办法就是基于其闭源的C++ SDK,使用本书中的各种开发方式,写一份Node.js 的C++ 扩展。这样就能把它们的C++ SDK 集成到我们的Node.js 项目中了。这是一个非常好的降低开发成本的方法。
当年我还在花瓣网的时候,有一个需求是提取一张图片的主题色。我当时翻阅了不少论文,最终采用了一种八叉树加最小差值法的结合体1 来完成这个需求。在数据结构和整型数字处理方面,我个人认为C++ 的开发效率和执行效率比Node.js 要高,于是我自然而然地就使用了C++ 把核心算法部分完成了(现在我甚至使用C 语言又重构了一套,开源在GitHub 上面2)。然后为了将其集成到我们的Node.js 任务调度系统中,我又将其封装成了一个Node.js 的C++ 的扩展。这样一来,主题色提取的任务就欢快地运行了——它也被开源在我的GitHub 上面,就是前面提到过的ThmclrX。而且借这个包的“东风”,我的硕士毕业论文写的就是这么一套主题色提取的任务系统相关内容。
类似的案例还有很多。如计算字符串哈希值等,由于用JavaScript 重写代码的时候,在整数的各种操作上会有很多“坑”,因此拿C++ 源码封装一下就非常简单了。甚至谷歌推出的CityHash 这个算法只有一份冗长的C++ 源码,使用JavaScript 重写的话将会是一个比较庞大的工作量;再比如解析MP4 文件的时长,我个人不是多媒体相关领域的开发者,所以并不擅长。于是我弄了一份C++ 的源码,懒得转换——嘿,用C++ 扩展一包,直接就发布了;还有同步获取HTTP API 的内容,写一个能继承的类似于ECMAScript 6 中Proxy 特性的拦截器;等等。
本书面向的读者
在阅读本书前,我希望你对Node.js 比较熟悉,并且对于C++ 这门语言至少要有一个初步的认识。当然,如果你的C++ 基础并不是很好的话,也不要怕,可以多读几遍本节最后的一段话。
本书不仅仅讲实践,我还花了不少篇幅来讲解它的前驱知识,如Chrome V8 引擎开发的一些基本概念,如句柄、句柄作用域等,以及各种API 的初步介绍。另外,书中还介绍了libuv 层面的内容,尤其是在异步方面,像libuv 中的线程、同步原语,以及如何在Node.js 的主时间循环中与你自身写的线程进行跨线程通信等。这么一算,Chrome V8、libuv,加上Node.js 的C++ 扩展开发,你相当于一下子买了3 本书,是不是觉得很超值?也就是说,你阅读本书的目的不一定是想要开发Node.js 的C++ 扩展;如果你想学习Chrome V8,或者想学习libuv,也可以参考本书。
本书的最后还简单展望了一下Node.js 8.0 之后出现的一个新特性,就是新一代Node.jsC++ 原生扩展接口N-API。不过由于N-API 还处于试验阶段,各种接口还不是很稳定,在未来随时会变,因此本书中并没有详细地介绍N-API,而只是简单讲解了它的思想,让大家在心中有一个思想准备。这样,哪一天N-API 正式发布了,读者就可以比较快地上手了。
不过,不要忘本,哪怕N-API 真的出来了,我还是希望大家多了解一下底层的基础,比如像Chrome V8、libuv 以及Node.js 源码相关的内容。因为学习了这些基础知识,对大家肯定没有坏处(甚至对于Node.js,大家说不定会有一个新的认识)。
最后,奉上我在一次技术直播中说过的一句话:“当我们在学习Node.js 的时候,我们其实就是在学编程。语言只是最表象的东西,思想才是核心内容。”如果还有部分读者由于本书需要有C++ 基础望而却步的话,多读几遍我刚才说的话,然后鼓起勇气入“坑”吧。
本书的结构
本书共分为9 章。其中前两章描述了一些基础的前驱理论知识;第3 章到第6 章讲的是Node.js 的C++ 扩展开发中用到的各种知识,并辅以简单的样例;第7 章和第8 章为实战章节,根据现实需求来完成相应的Node.js C++ 扩展;第9 章为对未来的N-API 的一个展望。
第1 章讲述了我们在学习本书内容之前所需要了解的基础,如Node.js 的模块机制与包机制,以及Node.js 都是由什么三方依赖构成的。其中就提到了很重要的Chrome V8 和libuv。本章的最后还讲述了要进行Node.js 的C++ 扩展开发所需要做的准备工作,包括但不限于编辑器的挑选、开发环境的搭建等。
第2 章主要讲述了什么是Node.js 的C++ 扩展,它的本质是什么,并且什么情况下需要使用C++ 扩展,以及阐述了为什么在这些情况下要使用 C++ 扩展。
第3 章介绍了谷歌的Chrome V8 引擎,从它与Node.js 的关系讲到它的一些基本概念,例如V8 的内存机制、基本对象等。在后续的章节中将开始介绍Chrome V8 的各种类及其概念,以及它们的用法,如句柄、句柄作用域、模板和各种常用的数据类型等。
第4 章相当于各种编程语言书籍中的“Hello World”,向读者介绍了binding.gyp 这个重要的配置文件,以及GYP 文件格式的基础,然后以几个最简单的例子向读者展示了Node.js 的C++ 扩展最简单的一些代码,包括函数的参数、回调函数的用法、对象的返回、函数的返回等,以及如何将一个C++ 的类封装成Node.js 中直接能用的类。
第5 章为大家介绍了NAN(Native Abstractions for Node.js)这个非常实用的包,使大家能在不同的Node.js 版本(本质上是各不兼容的Chrome V8 版本)中使用同一份C++ 代码。
第6 章讲解了如何使用libuv 进行异步Node.js 的C++ 扩展代码编程,首先介绍了libuv的一些基础概念,如句柄与请求等,然后讲述了如何使用libuv 进行跨线程编程。
第7 章就开始进入了实战环节。本章通过从零开始写一个基于C++ 的文件监视器扩展,讲述了要完成一个Node.js 原生扩展的一些流程。本章所述的文件监视器源码地址在https://github.com/XadillaX/node-efsw。
第8 章与第7 章的实战不同,对两个现有的简单C++ 扩展包进行分析,从另一个角度剖析了一个Node.js 的C++ 扩展包的源码。
第9 章展望了如何使用Node.js 的最新特性N-API 进行原生扩展的开发。不过我估计等到本书正式上市的时候,第9 章已经变成一个仅供参考的章节了。
阅读本书的注意事项
声明:我在编写本书之际,还在大搜车工作,所以书中的很多内容都是基于大搜车的角度来写的。比如8.2 节中有一处内容是这样的:
在笔者所在公司的内部,用了一套基于Dubbo 深度定制的RPC 服务框架。Node.js要访问这些Java 服务的RPC 函数是通过定制的HTTP 协议来完成的,所有的RPC服务节点都到Zookeeper 进行注册。
这里指的公司就是大搜车。再比如2.1.2 节中的一段话:
在官方的Node.js 版本ONS SDK 出来之前,笔者自己造了一个基于其官方C++ 版本的ONS SDK封装的轮子,用的当然是本书所讲的姿势——Node.js 的C++扩展了。
由于编写本书时我还并未从大搜车离职,因此这仍然是站在就职于大搜车的角度写的。我在编写本书之际,Node.js 的8.x 版本并未进入LTS1 阶段。于是我采用了Node.js 6.x作为样例进行了讲解,而Node.js 6.x 距离LTS 结束也还有一段时间。而且使用本书的方法进行Node.js 的原生扩展开发,在Node.js 6.x、Node.js 8.x 甚至是Node.js 9.x 下都是通用的。
本书中的样例都是基于Node.js v6.9.4 进行讲解的,读者在参考的时候上调或者下调几个中、小版本号问题都不大。
至于N-API 一章(第9 章),我在该章中也曾谈道:
本章内容在书中将会一带而过,因为在笔者写书的时候,N-API 还没有完全稳定下来,随时会改变。而且笔者个人认为,距离N-API 能正式投入生产用途的时间还很长。所以本章内容在本书中仅以扩展阅读的形式存在,其实关于N-API 的内容在5.1.2 节中曾略微提及。
因此,该章内容仅供参考,具体内容应以官方文档为准。
另外,本书所有的随书代码均在macOS 命令行下测试通过。理论上,它们也可以在Windows 和UNIX 上运行良好,但我并没有验证过。
最后,给出本书中经常用到的一些地址。
? 本书随书代码的Git 仓库:https://github.com/XadillaX/nyaa-nodejs-demo
? Node.js v6.9.4 代码仓库:https://github.com/nodejs/node/tree/v6.9.4
? Node.js v6.x 所对应的Chrome V8 文档:https://v8docs.nodesource.com/node-6.12/。若读者打开该地址,却发现页面不存在,可直接前往https://v8docs.nodesource.com/,
并点击“6.x”字样的超链接进入(注意该地址经常换)。
? 作者的个人技术博客:https://xcoder.in
? 作者的GitHub 地址:https://github.com/XadillaX
? Me:https://github.com/XadillaX/me
致谢
感谢我的妻子,她也是一位优秀的Node.js 研发工程师。她的支持是对我的最大鼓励,如果不是她,这本书的问世也许会更晚。
感谢我的父母,在我的背后默默地支持我的事业。在我很小的时候,他们就一直支持我追寻自己的梦想,这才使我能够在编程领域一路走下来。
感谢我的老东家大搜车,它营造了良好的技术与实践氛围,同事(包括领导)给予了我不少帮助,如书中图示的优化、阅读体验的建议等。这些同事有段鹏飞1、纪清华、刘佳楠、许波、王琦、袁小山……
感谢现实以及社区中的朋友们在本书创作的时候进行试读和探讨,并提供了一些其他帮助,他们包括但不限于Akagi201、ADoyle、David Cai、Hax(贺老)、贺星星、精子(jysperm)、孟德森、天然、五花肉、引证、张秋怡。
感谢为本书写序和推荐语的作者们: 安娜· 亨宁森(Anna Henningsen)、曹力(ShiningRay)、顾天骋(Timothy Gu)、桑世龙(狼叔)、雷宗民(老雷)、刘亚中(Yorkie)、迷渡(justjavac)、潘旻琦(pmq20)、田永强(朴灵)、袁锋(苏千)、孙信宇(芋头)、
王文睿博士、响马,你们一直是我们的楷模与学习对象。
感谢我的高中计算机老师兼NOIP 集训教练王震老师,王震老师是我在编程路上的启蒙老师,没有他就没有今天会写代码的我;也感谢当时陪我坚持走这一条路到毕业的好队友jiecchen 和MatRush;感谢我的大学ACM 教练宣江华老师和一直为集训队默默付出的陈萌老师;还要感谢我的研究生导师李启雷博士传道受业。
感谢博文视点的刘皎女士以及她的团队,是他们的努力使本书最终能与广大读者见面,他们提出的专业意见给了我很多帮助。
最后,还要特别感谢董伟明(《Python Web 开发实战》作者)。在阅读了他的一篇文章《写一本技术书籍》后,我才有了写作本书的想法,并最终付诸实施。
死月(朱凯迪)
2018 年3 月于杭州
序一
1995 年Brendan Eich 花了10 天时间开发出了一门脚本语言,用来弥补Java Applet 的不足,随后Marc Andreessen 给它起名为Mocha。其最初的定位是,Java 用于大型专业级开发,而Mocha 则是给测试脚本编写人员、业余爱好者、设计师使用的。
1995 年5 月,Mocha 被集成到了Netscape 浏览器中,其不久后改名为LiveScript,当年年底网景公司和Sun 公司达成协议并获得了Java 商标的使用权,其正式更名为JavaScript。
有人说Sun 公司的介入限制了Brendan Eich 的手脚。JavaScript 除了某些语法和Java 类似以外,骨子里却是完全不一样的东西。
也有人说正式改名为JavaScript 才使得这门语言成为浏览器执行的唯一语言。
时至今日JavaScript 已经不仅仅局限于为网页做特效了,而真正发展成为一门全功能的编程语言:
? 2008 年Chrome 发布、V8 发布;
? 2009 年Node.js 发布;
? 2010 年NPM 发布;
? 2014 年12 月,多位核心Node.js 开发者不满于Joyent 对Node.js 的管理制度,创建了io.js;
? 2015 年初Node.js 基金会成立;
? 2015 年9 月Node.js 4.0 发布,Node.js 和io.js 正式合并。
Node.js 4.0 版引入了ES6 的语言特性和“长期支持版本”的发布周期。
如今Node.js 社区已经成为最活跃的编程社区之一,而从NPM 的包数量来看,其已经超越了Java 的Manven、Ruby 的gem、PHP 的composer。VIII Node.js:来一打C++ 扩展但是Node.js 仍有很多不足之处,Node.js 的使用者绝大部分仅仅把Node.js 作为前端开发的辅助工具。大家把Node.js 作为后端主力开发平台使用时,遇到CPU 密集的场景时又不得不借助Java 或者Go。虽然V8 引擎一直致力于让JavaScript 运行得更快,但是和Java、C++ 相比,还有不小的性能差距。
虽然关于JavaScript 的书已经汗牛充栋,但是有关Node.js 原理的书却屈指可数。而目前真正能够深入介绍原理的,国内的图书中也只有朴灵的《深入浅出Node.js》了,但如今四五年过去了依然没有等到该书的第2 版,而死月的这本书却可以弥补这一方面的不足。
所有的编程语言底层都会回归C/C++,Node.js 的底层依赖库V8 使用C++ 开发,libuv 则使用C 语言。而使用C++ 开发Node.js 扩展将直接把擅长CPU 的C++ 和擅长I/O 的Node.js结合在了一起,弥补了JavaScript 在计算密集型应用方面的不足。
我从2015 年开始研究V8,认识死月的时间则更早。死月不仅仅精通C++,他也是国内的Node.js 布道师之一。从我认识他起,他就一直在使用Node.js。如果你想深入了解Node.js 的原理,或者想打开Node.js 另一个世界的大门,这本《Node.js:来一打C++ 扩展》值得你精读。
——迷渡(justjavac),Flarum 中文社区创始人,国内知名前端技术专家
2018 年3 月22 日于天津
序二
我跟死月相识于GitHub,那时我们经常会向Node.js 贡献一些代码,彼此也会在微信上讨论一些技术问题。当我听说死月在写一本关于Node.js C++ 扩展相关的图书时,激动得几乎要从床上蹦起来。因为我深知一个对Node.js 与V8 引擎都如此了解之人,愿意将他所知所想分享出来,这将是给予社区的一份大礼。
从我个人的角度来看,这本书非常适合这类开发者:他们对于Node.js 的使用已经了然于胸,但却苦于没有底层开发经验,对整个V8 虚拟机也一知半解。这时,他们可以从第3 章开始读起。本书用了很长的篇幅介绍JavaScript 代码究竟在虚拟机里是怎么运行的,它们又都分别对应着哪一类数据结构等。因为作者深知,只有把这些基础理解透了,则无论是开发C++ 扩展,还是写纯JavaScript 代码,大家都能更得心应手。
本书像是在述说着Node.js 在C++ 扩展这一课题中曲折而又有趣的历史进程。首先从最原始的V8 API 时代开始。对于每个原始时代,开发者最痛苦的莫过于解决各种版本的兼容问题。之后迎来的是NAN 时代。它解决了原始时代的接口抽象问题,接口也更丰富多样,异步接口也封装在内。最后,是还在路上的N-API。它与NAN 一脉相承,拥有更官方的支持和更友好的接口。
另外,我们通常在写一个C++ 扩展时,多数情况下会跟异步打交道,这其中包含着如何非阻塞地调用底层接口,如何将异步的结果返回到JavaScript 的回调函数中,以及如何正确地在异步封装中释放你的资源。对这些内容特别感兴趣的读者,可以打开第6 章一睹为快。
Node.js 已快走完它的第一个10 年,尽管被人诟病于其回调地狱、虚假繁荣、超高并发场景下的不适应性,以及低端设备上的内存等问题,但这仍旧无法阻止它前进的步伐。然而对于我们Node.js 工程师来说,除了掌握好这门语言之外,学习如何写C++ 扩展、了解它如X Node.js:来一打C++ 扩展
何运转将是我们下一阶段的重要功课。相信《Node.js:来一打C++ 扩展》将会成为常伴大家左右的另一本《代码大全》。
——刘亚中(Yorkie),Rokid 系统工程师,tensorflow-nodejs 作者
2018 年3 月22 日于杭州
1 Node.js 的 C++ 扩展前驱知识储备 1
1.1 Node.js 的模块机制 2
1.1.1 CommonJS 的模块规范 2
1.1.2 Node.js 的模块 4
1.1.3 小结 9
1.1.4 参考资料 9
1.2 Node.js 的包机制 9
1.2.1 CommonJS 的包规范 9
1.2.2 Node.js / NPM 下的包 13
1.2.3 NPM 与 CNPM 16
1.2.4 小结 19
1.2.5 参考资料 19
1.3 Node.js 依赖简介 20
1.3.1 Chrome V8 20
1.3.2 libuv 25
1.3.3 其他依赖 28
1.3.4 小结 30
1.3.5 参考资料 30
1.4 C++ 扩展开发的准备工作 31
1.4.1 编辑器 / IDE 31
1.4.2 node-gyp 36
1.4.3 其他构建工具 54
1.4.4 小结 56
1.4.5 参考资料 56
2 C++ 模块原理简析 57
2.1 为什么要写 C++ 模块 57
2.1.1 C++ 比 JavaScript 解释器高效 57
2.1.2 已有的 C++ 轮子 72
2.1.3 小结 77
2.1.4 参考资料 77
2.2 什么是 C++ 扩展 78
2.2.1 C++ 模块本质 78
2.2.2 Node.js 模块加载原理 80
2.2.3 小结 102
2.2.4 参考资料 103
3 Chrome V8 基础 104
3.1 Node.js 与 Chrome V8 104
3.2 基本概念 105
3.2.1 内存机制 105
3.2.2 隔离实例(Isolate) 108
3.2.3 上下文(Context) 109
3.2.4 脚本(Script) 110
3.2.5 小结 110
3.2.6 参考资料 111
3.3 句柄(Handle) 111
3.3.1 本地句柄(Local) 112
3.3.2 持久句柄(Persistent) 115
3.3.3 永生句柄(Eternal) 119
3.3.4 待实本地句柄(Maybe Local) 119
3.3.5 小结 121
3.3.6 参考资料 121
3.4 句柄作用域 121
3.4.1 一般句柄作用域(Handle Scope) 122
3.4.2 可逃句柄作用域(Escapable Handle Scope) 125
3.4.3 小结 129
3.4.4 参考资料 129
3.5 上下文(Context) 129
3.6 模板(Template) 133
3.6.1 函数模板(Function Template) 133
3.6.2 对象模板(Object Template) 138
3.6.3 对象模板的访问器(Accessor)与拦截器(Interceptor) 144
3.6.4 对象模板的内置字段(Internal Field) 175
3.6.5 函数模板的继承(Inherit) 183
3.6.6 小结 188
3.6.7 参考资料 189
3.7 常用数据类型 189
3.7.1 基值(Value) 189
3.7.2 字符串(String) 194
3.7.3 数值类型 196
3.7.4 布尔类型(Boolean) 196
3.7.5 对象(Object) 196
3.7.6 函数(Function) 200
3.7.7 数组(Array) 202
3.7.8 JSON 解析器 203
3.7.9 函数回调信息(Function Callback Info) 203
3.7.10 函数返回值(Return Value) 204
3.7.11 隔离实例(Isolate) 204
3.7.12 小结 205
3.7.13 参考资料 206
3.8 异常机制 206
3.8.1 try-catch 206
3.8.2 抛出异常 209
3.8.3 异常生成类(Exception) 211
3.8.4 小结 211
3.8.5 参考资料 211
4 C++ 扩展实战初探 212
4.1 binding.gyp 212
4.1.1 惊鸿一瞥 213
4.1.2 binding.gyp 基础结构 213
4.1.3 GYP 文件 214
4.1.4 常用字段 221
4.1.5 小结 228
4.1.6 参考资料 228
4.2 牛刀小试 229
4.2.1 又是 Hello World 229
4.2.2 函数参数 232
4.2.3 回调函数 234
4.2.4 函数返回 238
4.2.5 小结 239
4.2.6 参考资料 240
4.3 循序渐进 240
4.3.1 C++ 与 JavaScript 类封装 240
4.3.2 实例化 C++ 类封装对象的函数 250
4.3.3 将 C++ 类封装对象传来传去 253
4.3.4 进程退出钩子 255
4.3.5 小结 259
4.3.6 参考资料 259
5 Node.js 原生抽象——NAN 260
5.1 Node.js 原生模块开发方式的变迁 260
5.1.1 以不变应万变 260
5.1.2 时代在召唤 261
5.1.3 小结 267
5.1.4 参考资料 267
5.2 基础开发 267
5.2.1 什么是 NAN 267
5.2.2 安装和配置 269
5.2.3 先睹为快——搭上NAN 的快车 270
5.2.4 基础帮助函数和宏 276
5.2.5 忽略 node_modules 279
5.2.6 小结 279
5.2.7 参考资料 280
5.3 JavaScript 函数 280
5.3.1 函数参数类型 280
5.3.2 函数声明 282
5.3.3 函数设置 288
5.3.4 小结 296
5.3.5 参考资料 296
5.4 常用帮助类与函数 296
5.4.1 句柄相关 296
5.4.2 创建数据对象 298
5.4.3 与数据对象“玩耍” 300
5.4.4 封装一个类 314
5.4.5 异常处理 315
5.4.6 小结 315
5.4.7 参考资料 316
5.5 NAN 中的异步机制 316
5.5.1 Nan::AsyncQueueWorker 316
5.5.2 Nan::Callback 317
5.5.3 Nan::AsyncWorker 317
5.5.4 Nan::AsyncProgressWorker 323
5.5.5 小结 327
5.5.6 参考资料 327
6 异步之旅——libuv 328
6.1 基础概念 329
6.1.1 事件循环 330
6.1.2 句柄(Handle)与请求(Request) 333
6.1.3 尝尝甜头 335
6.1.4 小结 340
6.1.5 参考资料 340
6.2 libuv 的跨线程编程基础 341
6.2.1 libuv 的线程 342
6.2.2 同步原语(Synchronization Primitive) 347
6.2.3 工作队列 355
6.2.4 小结 356
6.2.5 参考资料 357
6.3 跨线程通信 357
6.3.1 uv_async_t 句柄 357
6.3.2 Watchdog 半成品实战解析 358
6.3.3 Watchdog 试运行 367
6.3.4 小结 368
6.3.5 参考资料 369
7 实战——文件监视器 370
7.1 准备工作 370
7.1.1 功能规划 370
7.1.2 文件系统监听库——efsw 373
7.1.3 小结 376
7.1.4 参考资料 376
7.2 核心设计 376
7.2.1 API 设计 377
7.2.2 EFSWCore 的血肉之躯 377
7.2.3 EFSWCore 的灵魂 381
7.2.4 小结 385
7.3 编写JavaScript 类 386
7.3.1 类的设计 386
7.3.2 核心逻辑 388
7.3.3 简单容错 391
7.3.4 小结 393
7.4 进一步完善 393
7.4.1 C++ 代码的完善 393
7.4.2 JavaScript 代码的完善 398
7.4.3 小结 400
8 实战——现有包剖析 401
8.1 字符串哈希模块——Bling Hashes 401
8.1.1 文件设定 402
8.1.2 C++ 源码剖析 403
8.1.3 JavaScript 源码剖析 408
8.1.4 小结 409
8.1.5 参考资料 410
8.2 类 Proxy 包——Auto Object 410
8.2.1 Proxy 410
8.2.2 Auto Object 使用范例 412
8.2.3 代码剖析 415
8.2.4 小结 424
8.2.5 参考资料 424
9 N-API——下一代 Node.js C++ 扩展开发方式 425
9.1 浅尝辄止 426
9.1.1 实现一个 Echo 函数 426
9.1.2 尝试运行 N-API 扩展 430
9.1.3 向下兼容 431
9.1.4 N-API Package——C++ 封装 433
9.1.5 小结 433
9.1.6 参考资料 433
9.2 基本数据类型与错误处理 433
9.2.1 基本数据类型 433
9.2.2 与作用域及生命周期相关的数据类型 435
9.2.3 回调数据类型 438
9.2.4 错误处理 439
9.2.5 模块注册 441
9.2.6 小结 442
9.2.7 参考资料 442
9.3 对象与函数 442
9.3.1 对象 442
9.3.2 函数 448
9.3.3 类的封装 453
9.3.4 小结 455
9.3.5 参考资料 455