Node.js的C++扩展教程(一)

今天我们来讲一点基础性的知识。

Node.js已经能涉猎包括但不限于后端、工具脚本、GUI客户端等各种领域。

Node.js的模块机制

1. require()

做过Node.js开发的人员都使用过require()这个函数,像操作文件使用const fs = require(‘fs’),操作网络使用const net = require(‘net’)…等等。
require就是用来引用一个模块(module,模块是node.js的基本单位)的。类似于我们使用C++在Windows上通过LoadLibrary来加载第三方库一样。
在Node.js中是通过exports来到导出模块中的变量、对象、函数等等。
也就是说,在一个module里,我们通过require(…)来引入其他的模块,通过module.exports {…}来到处本模块里的变量、对象、函数…
示例:

//Pet.js
function Pet () {
 this.name = 'Dog'
}

const dog = Pet()
module.exports = {
  'dog': dog
}

2.Node.js的模块

Node.js的应用通过入口文件之后,是由一个个模块组成的。通常一个模块是一个遵循CommonJS规范书写的JavaScript源文件,也有可能是一个后缀为.node的C++二进制文件,这些文件通过Node.js的require()函数被引入并使用。

Node.js的模块按照寻径方式通常分为两种:

  • Node.js核心模块:代码存在于Node.js源码库中,并且将其API暴露给开发者的模块。
  • 文件模块:是指那些需要Node.js进行文件寻径获得的模块。通常有两种方式:一种是找到index.js/index.json/index.node文件方式,一种是找到package.json中main字段对应的js文件。

3.模块缓存

在Node.js的运行中,通常情况下一个包一旦被加载了,那么在第二次执行require()的时候就会在缓存中获取暴露的API,而不会重新加载一遍该模块里面的代码再次返回。

Node.js依赖简介

Node.js并不是一个从头开发的项目,它是在Chrome V8以及libuv等一些三方库的基础上进行的封装。

1.Chrome V8

想必大家都应该知道在浏览器的世界里有这么一款 “霸主” 地位的浏览器-Chrome。在2008年发布以来,一直是浏览器市场的佼佼者,谷歌在2008年也开源了V8引擎的源码。

后面我们也会详细说下V8的世界是什么样子的。

2.libuv

libuv是一个专注于异步 I/O 的跨平台类库(C/C++)。实际上它主要为Node.js开发。Node.js的事件循环就是基于libuv的。

3.其他依赖

  • http-parser:这是一个C实现的HTTP消息解析器,其能解析HTTP协议的请求数据和返回数据。
  • OpenSSL:OpenSSL是一套安全套接字层协议库。OpenSSL主要由C语言编写,实现了基本的加密功能:SSL和TSL。
  • zlib:zlib是一个老牌的年代久远的提供数据压缩功能的库,在很多应用程序中都会有zlib.dll这个库。

node-gyp

之所以把这个指令作为一个单独的标题,是因为它很重要,后期的开发用的很多。

node-gyp是Node.js下的C++扩展构建工具。几乎所有的Node.js C++扩展都由它构建的。

node-gyp有以下几个子命令:

  • node-gyp build:调用msbuild以构建模块(在Windows下是msbuild,若在UNIX下则会是make)。
  • node-gyp clean:清理生成的构建文件以及out目录。
  • node-gyp configure:为当前模块生成MSVC项目配置文件(在Windows下是MSVC,若在UNIX下则是Makefile)。
  • node-gyp rebuild:一次性依次执行clean / configure和build。
  • node-gyp install:为指定版本的Node.js安装开发环境。
  • node-gyp list:输出当前安装的Node.js开发环境。
  • node-gyp remove:移除指定版本的Node.js开发环境文件。

使用node-gyp的C++扩展主要由一个binding.gyp文件进行配置。详细内容后面教程会介绍。

什么是C++扩展

由于Node.js本身就是基于Chrome V8引擎和libuv,用C++进行开发的,因此自然能轻而易举对特定结构下使用了特定的API进行开发的C++代码进行扩展,使得其在Node.js中被 “require” 之后能像调用JavaScript函数一样调用C++扩展里面的内容。

1.C++模块本质

后缀名为.node的模块,其实就是一个C++模块的二进制文件。诸如Windows下的dll文件、Linux下的so文件以及macOS下的dylib文件一样,*.node也是一个动态库。

所以,在Node.js中引入一个C++模块的过程,实际上就是Node.js在运行时引入了一个动态链接库的过程。运行时接受JavaScript代码中的调用,解析出来具体是扩展中的哪个函数/类需要被调用,在调用完获得结果之后再通过运行时返回给JavaScript代码。
在这里插入图片描述
调用Node.js的原生C++函数和调用C++扩展函数的区别就在于前者的代码会直接编译进Node.js可执行文件中,而后者的代码则位于一个动态链接库中。

发布了10 篇原创文章 · 获赞 0 · 访问量 119

猜你喜欢

转载自blog.csdn.net/weixin_42071117/article/details/104759898