JS怎么调用C++

Node.js不是什么

不是web结构

  • Node.js并不是web后端结构
  • 所以不能把Node.js与Flask或Spring比较

不是编程言语

  • Node.js并不是后端的JS
  • 所以不能把Node.js与Python或PHP对比

Node.js是什么

是一个渠道

  • 它将多种技能组合起来
  • JavaScript也能调用体系接口、开发后端应用

Node.js组合了许多技能

  • V8引擎
  • libuv
  • C/C++完结的c-ares(域名解析)、http-parser(解析http)、OpenSSL(做https)、zlib(做加密)等库

Node.js技能架构

Node.js技术架构

随着Node.js的版别现已从0.8升级到12.11.1,其架构也在一向改变中

假如要看源代码,引荐看0.10版别,github中找到nodejs选择0.10版别即可

github.com/nodejs/node…

由于这一版别运用了好久一段时刻,并且源代码比新版少许多

假如想要了解更多,能够查看 github.com/yjhjstz/dee…

咱们大部分时分,只需求学习Node.js规范库即可

对于其他模块,有一个大约的了解就行

等对Node.js内部完结感兴趣的时分,再去了解规范库之外的东西

不过你可能要写好 C / C++

什么是bindings

布景

  • C/C++完结了一个http_parser库,很高效
  • 咱们只会写JS,但是又想调用这个库
  • 直接调用必定是不能成功的,咱们需求一个中心的桥梁

bindings

  • Node.js用C++对http_parser进行封装,使它契合某些要求(如:它的数据类型和JS数据类型做了一一对应的封装),封装的文件叫做http_parser_bindings.cpp(C++的代码)
  • 用Node.js供给的编译东西将其编译为.node文件
  • JS代码能够直接require这个.node文件
  • 这样JS就能调用C++库,中心的桥梁便是binding(http_parser_bindings.cpp)
  • 由于Node.js供给了许多binding,所以加个s
  • 这便是bindings

JS 与 C++ 交互

查看: nodejs.cn/api/addons.…

插件通常会露出能够从 Node.js 中运转的 JavaScript 拜访的目标和函数。 当从 JavaScript 调用函数时,输入参数和回来值必须映射到 C/C++ 代码和从 C/C++ 代码映射。

Node.js技术架构

在test.js就完结了经过JS引入addon这样的node.js文件,调用了addon.cc(C/C++)中的add方法

C++ 调用JS回调

查看: nodejs.cn/api/addons.…

插件中的常见做法是将 JavaScript 函数传给 C++ 函数并从那里履行它们

Node.js技术架构

args[0]便是JS中的那个函数,但是args[0]不能直接给C++,C++是看不懂JS函数的,Node.js供给了Cast的东西,它能够把JS的函数转化为C++能看懂的函数cb。JS中的函数addon就会被C++调用,调用的时分传了参数hello world(C++中结构了JS能看懂的string) ,于是就输出了hello world

只要能让JS调用C++的代码,JS的才能就会被无限扩大

Node.js供给的binding咱们能够运用,假如现在有一个新的C++库,Node.js没有把它绑定进来怎么办?

Node.js还供给别的一个功用: 答应你自己写C++,把C++库绑定到JS上,JS就能够调用C++库了,这便是Node.js的别的一个才能,C/C++插件(自定义其他才能)

Node.js的依靠

Node.js技术架构

在Node.js V0.10 版别中有7个依靠,咱们主要需求掌握两个依靠v8和uv(也便是libuv),其他的优先级往后放

  • cares:DNS
  • http_parser: http
  • npm: 包办理器
  • openssl: https
  • zlib: 压缩

libuv & v8 的功用

libuv是什么

布景

  • FreeBSD 体系上有kqueue
  • Linux体系上有epoll
  • Windows 体系上有IOCP
  • Ryan为了完结一个跨渠道的异步I/O(所有的输入和输出,如:写文件,拜访网络,连接打印机打印文件即体系和外界进行的所有交互)库,开始写libuv
  • libuv会依据体系主动选择合适的计划(kqueue/epoll/IOCP)

功用

  • 能够用于TCP(http是基于TCP/IP,只要能操作TCP就能够做http服务器)/UDP(QQ谈天)/DNS(baidu.com对应的IP)/文件(文件的读取)等的异步操作
  • 有了这些功用Node.js就能够脱节IO瓶颈了,涉及到IO的操作交给C言语去做,JS只负责简单的调用

v8是什么

功用

  • 将JS源代码变成本地代码(01)并履行
  • 保护调用栈,确保JS函数的履行次序
  • 内存办理,为所有目标分配内存
  • 废物收回,重复运用无用的内存(废物收回的目的是为了再次重复运用,由于内存是有限的,比方:你用完了2k的内存,用完了就得还给我,还要给下一程序运用呢!)
  • 完结JS的规范库(如:数组的sort、数组的splice等函数)
  • v8自身是多线程的

留意

  • V8不供给DOM API(如:在V8中不能操作douemnt.createElement()...,它是浏览器供给的)
  • V8履行JS是单线程的(V8自身是多线程的)
  • 能够敞开两个线程分别履行JS(并不是真实意义上的多线程,这两个线程之间毫无瓜葛)
  • V8自身是包括多个线程的,如:废物收回为单独线程
  • 自带 eventloop 但 Node.js并没有运用自带的eventloop而是基于libuv自己做了一个eventloop

eventloop

Event Loop 是什么

什么是Event

  • 计时器到了就会发生一个工作,这个工作发生就会履行回调(内部的)
  • 文件能够读取了、读取出错了的时分是操作体系要单独生成一个工作告知JS。如:复制文件到U盘上,假如发现此刻现已有别的一个文件也在复制,那么此刻第二个复制文件就会很慢,由于硬盘的读写速度是有极限的(外部的,文件再在硬盘上,而硬盘和操作体系是分开的)
  • socket有内容了、关闭了。如:用户恳求了咱们的服务器,socket有内容了操作体系得告知JS要开始读用户的内容。socket关闭了,也得告知JS(外部的,socket一般为别的一台机器传过来的)

什么是Loop

  • Loop 便是循环,比方: while(true) 循环
  • 由于工作是分优先级的,所以处理起来也是分先后的

举例:

三种不同的工作

setTimeout(f1,100)        // 计时器届时了
fs.readFile('/1.txt',f2)  // 文件能够读了
server.on('close',f3)     // 服务器关闭了

假如一起触发,Node会怎么办?履行f1?f2?f3

- 必定会有某种次序(优先级)
- 这种次序应该是人为规则的(假如有读文件就先读文件 => 假如有恳求就先处理恳求=>假如有计时器就履行计时器 ====> 进入循环Loop => 假如有读文件就先读文件 => 假如有恳求就先处理恳求 => .......)
  • 所以Node.js需求依照次序轮询每种工作
  • 这种轮询往往都是循环的,1->2->3->1->2->3

EventLoop

  • 操作体系能够触发工作,JS能够处理工作
  • Event Loop 便是对工作处理次序的办理

Event Loop

次序示意图

Node.js技术架构

  • 读官方文档是最好的方法
  • 或许/post/684490…

重点阶段

  • timers 查看计时器
  • poll 轮询阶段,处理大部分恳求(如:读文件,http恳求),查看体系工作
  • check 查看阶段,处理 setImmediate 回调
  • close callbacks 看下有没有sockert关闭的回调
  • 再回到timers 查看计时器。。。 如此循环下去
  • 假如Node.js发现没有什么事做就会停在poll(轮询)阶段,假如发现有工作做,如履行setImmediate就会进入下个阶段check(while循环,一向问操作体系有没有文件能够读、有没有网络恳求能够处理、。。。。)。poll阶段是Node.js停留时刻最长的、优先级最高的
  • 其他阶段用的较少

大部分时分timers中的定时器是后履行的(虽然它在最前面),由于定时器至于在大于或等于时刻的时分才会被履行,假如时刻没到就会履行timers下面的阶段,等其他阶段如poll阶段或许check阶段履行完了,计时器的时刻到了或许超了再履行timers

一个面试题

请问下面的代码哪个先履行?

setTimeout(f1,0)
setImmediate(f2)

===》 不确定

(1) 大部分情况下是setImmediate先履行,由于大部分时分,Node.js都是停留在poll 阶段,这个时分假如要履行JS就会先经过check阶段,这个阶段便是处理setImmediate

(2) 有一个情况是破例的: Node.js第一次进来时会先看下有没有timers

留意

  • 大部分时刻,Node.js都停留在poll轮询阶段(假如这个阶段比较耗时,那么timers就会主动往后推)
  • 大部分工作都在poll阶段被处理,如文件、网络恳求

总结

  • 用libuv进行异步I/O操作(如:让libuv读文件,文件读完后Node.js顶替后边的工作(Node.js能够处理文件了!!!)
  • 用event loop 办理不同工作处理次序(先polls(操作体系) -> check -> close -> timers -> polls(操作体系) … 如此循环) (Node.js能够办理工作的次序了!!!)
  • 用C/C++ 库高效处理DNS/HTTP…(Node.js又能够处理网络了!!!)(由于Node.js是凭借C++处理网络恳求,因而处理网络恳求速度很快)
  • 用bindings 让JS能和C/C++沟通(JS也能够调用C++的代码了!!!)(把C++代码编译成.node文件给JS去require,require的进程中JS传个函数给C++,C++调用JS)
  • 用V8运转用户写的JS(写好了JS代码在哪里运转JS代码呢?)
  • 用Node.js规范库进化JS代码(都让用户写JS,用户就不爽了,帮用户写好了一些东西,用户直接用)
  • 这便是Node.js

Node.js作业流程

Node.js技术架构

  • Application便是咱们写的JS
  • 咱们写JS放到V8上运转
  • 运转的进程中发现JS中写了一个定时器
  • Node.js调用Node.js的bindings / API ,把定时器放到 Event Loop 中,告知Event Loop 100毫秒之后要履行一个函数
  • Event Loop 中有许多不同的队列(如:timers、poll、check等),Event Loop 会等待恰当的时机去履行队列中的代码
  • 假如此刻在poll阶段需求读一个文件,这时Event Loop 就会运用libuv开一个线程去读这个文件(JS不参与),读完文件之后,操作体系就会回来一个工作给Event Loop,Event Loop 发现文件读好了,就传回给V8,然后就传回到咱们写代码的当地
  • 处理网络恳求也一样libuv得到了用户传过来的网络恳求,就会把它放到 Event Loop 中的poll阶段,poll阶段得到这个恳求之后,就会调用JS代码把它在v8中履行,将成果回来到写diamagnetic的当地

整个进程咱们发现:V8 和 libuv是最重要的,而Node.js中的bindings / API 便是V8 和 libuv 中心的桥梁,咱们写的代码仅仅整个渠道中很小的一部分,这便是Node.js的作业流程

咱们写的代码 ==> V8上运转 ==> V8经过Node.js的bindings/API ==> 运用libuv供给的功用 / 其他的C++供给的功用完结用户所需求的功用

因而说Node.js不是一门言语,也不是一个结构,它便是一个渠道!!!

Node.js API与学习思路

Node.js技术架构

接下来咱们只需求架构图中最上面的一块 Node.js API(官方供给的函数)

API文档

官方地址

  • 英文文档 nodejs.org/api/
  • 中文文档 nodejs.cn/api/

这些文档更像是字典,实在是太多了,没有欲望经过阅读文档去学习

民间版别(引荐)

  • devdics.io: devdocs.io/
  • 进入之后敞开Node.js 10 LTS
  • 搜索功用十分便利
  • 可敞开主题
  • 可离线观看

Node.js技术架构

API到底有哪些功用

重点关注黄色标示的API

Node.js技术架构

  • Buffer: 一小段缓存(大文件一点一点上传)
  • Child Processes: 子进程(Node.js的分身)
  • Cluster: 集群 (把多个Node.js集合到一起,每个Node.js做不同的工作,它们之间的联系便是主要和非必须的联系)
  • Debugger: 调试
  • Events: 对应的便是EventHub,发布订阅模式(一个目标供给了on、off、emit)
  • File System: 文件体系,操作文件/目录
  • Globals: 全局变量,如:__dirname:当时文件所在目录;__filename: 当时文件的文件名
  • Http
  • Path: 途径
  • Query Strings: 处理URL
  • Stream: 流格式的数据的处理
  • Timers: settimeout 、setInterval、setImmediate
  • URL
  • Worker Threads*

学习路线

根底 – Web – 结构

  • 先学根底,以使命为导向学习
  • 逐个学习文件、HTTP、Stream等模块
  • 在学Web、数据库、AJAX相关知识
  • 最后学习结构,以项目为导向
  • 以Express为切入点,制造完整网站

约定

  • 记笔记,写博客
  • CRM学习法贯穿整个学习进程(copy => run => modify,学习任何技能最快的方法)
  • 学习调试东西和思路