Node-FFI 不得不说的原理 - Dosk技术站
← Home About Archives Subscribe
Node-FFI 不得不说的原理
May 15 2018
Node-FFI 不得不数说的原理
自己在实际开发中总结的东西
从计算机基础开始讲起
-
线程, 进程, 协程
-
函数调用约定, 指针, (动态/静态)链接库
-
符号表
回到 Node.js 的部分
Demo 运行截图(N-API 为实验性特性所以会有一个警告):
其中第三种方案其实是借助
libuv
的接口实现,此前这种方式仅仅是因为Node.js 使用了
uv_default_loop
,不过在 N-API 中被官方支持了:
- Event Loop, GC
- 简单来说: 一个分阶段的线程,通常我们称为 JS 主线程,V8 中使用
uv_default_loop
实现 - GC: 即垃圾回收,垃圾回收是相对于我们编译器编译阶段可见的上下文为准的,即一个动态链接库的对象生命周期对调用它的程序不可见
- 简单来说: 一个分阶段的线程,通常我们称为 JS 主线程,V8 中使用
Node-FFI: 令人兴奋的跳跃
-
从载入动态库说起
a. 其实大部分编译型语言是具备载入动态库的能力的,因为操作系统已经提供了相关的封装,但是必须是编译前定义好被调用函数结构、函数调用规则等
b. 动态类型语言是运行在 VM 之上,而此时的 VM 已经是是编译过的二进制模块,已经不具备上文所说的特性
-
libffi: Node-FFI 的核心
a. 优势: 可以动态定义函数的调用方法,可以动态定绑定函数实体到指针
b. 应用:
OpenJDK, Dalvik, CPython
等非常著名的引擎: libffic. 实现:
特性
实现方式
实现语言
定义函数
通过定义 ffi_cif
结构体描述函数,并通过模拟函数调用方式实现调用
inline asm
绑定函数
通过定义 ffi_closure
绑定 ffi_cif
到指定函数并返回一个函数指针,当调用这个指针,指针指向的函数通过 ffi_cif
结构体的定义模拟取栈的操作并传入被绑定的函数
inline asm
Node-FFI: 函数回调的实现
-
流程实现
- 太长了,参见源码与我的讲解: callback_info.cc
-
源码角度展开
-
回调的惊险跳跃: 多线程回调如何变成单线程 && 如何 invoke 进入 JS EventLoop
题外话
- 让我想想再说…
[
Dosk技术站 SpringHack的无名技术小站
](/about/)
Load Comments
var cmts={ load:function cmts(){ var gitment = new Gitment({ id: “Node-FFI 不得不说的原理”, owner: “springhack”, repo: “SpringHack”, oauth: { client_id: “6c8cd45b9c7d253393be”, client_secret: “ef45833d84aefdec5b79937d192eeadba3568a64”, }, }) gitment.render(‘gitment’); var loadcmt = document.getElementById(“loadcmts”); var imyourfather = loadcmt.parentNode; imyourfather.removeChild(loadcmts) } }
Read more
-
Nov 11 2018
-
Nov 02 2018
-
May 15 2018
-
Jan 01 2018
-
Aug 31 2017
-
Aug 29 2017
-
Jul 02 2017
-
Apr 18 2017
-
Apr 09 2017
-
Mar 22 2017
© Copyright 2018 SpringHack / Hexo / Lightime
(function(i,s,o,g,r,a,m){i[‘GoogleAnalyticsObject’]=r;i[r]=i[r] | function(){ (i[r].q=i[r].q | []).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,’script’,’https://www.google-analytics.com/analytics.js’,’ga’); ga(‘create’, ‘UA-XXXXXXXX-Y’, ‘auto’); ga(‘send’, ‘pageview’); InstantClick.on(‘change’, function() { ga(‘send’, ‘pageview’, location.pathname + location.search); }); InstantClick.init(‘mousedown’); |