node源码详解(四) —— js代码如何调用C++的函数

知识共享许可协议本作品采用知识共享署名 4.0 国际许可协议进行许可。转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource4 
本博客同步在https://cnodejs.org/topic/56ed249356d74f3d3624b3ff 
本博客同步在http://www.cnblogs.com/papertree/p/5285705.html


  上面讲到node调用Script::Compile()和Script::Run()解析执行app.js,并把io操作和callback保存到default_loop_struct,那么app.js里面js代码如何调用C++的函数呢?

  在4.2节进行解释,先在4.1节来点知识预热。

4.1 V8运行js代码的基础知识 —— V8的上下文

  来看看google V8开发者文档的一点介绍:(地址:https://developers.google.com/v8/get_started)

  • context is an execution environment that allows separate, unrelated, JavaScript code to run in a single instance of V8. You must explicitly specify the context in which you want any JavaScript code to be run.

  大概意思就是context(上下文)是用来执行javascript代码的运行环境,而且运行javascript代码的时候必须指定一个context。

  从文档里面摘了一段hello world代码:

int main(int argc, char* argv[]) {// Initialize V8.
  V8::InitializeICU();V8::InitializeExternalStartupData(argv[0]);Platform* platform = platform::CreateDefaultPlatform();V8::InitializePlatform(platform);V8::Initialize();// Create a new Isolate and make it the current one.
  ArrayBufferAllocator allocator;Isolate::CreateParams create_params;create_params.array_buffer_allocator = &allocator;Isolate* isolate = Isolate::New(create_params);{Isolate::Scope isolate_scope(isolate);// Create a stack-allocated handle scope.
    HandleScope handle_scope(isolate);// Create a new context.Local<Context> context = Context::New(isolate);// Enter the context for compiling and running the hello world script.
    Context::Scope context_scope(context);// Create a string containing the JavaScript source code.Local<String> source =String::NewFromUtf8(isolate, "'Hello' + ', World!'",NewStringType::kNormal).ToLocalChecked();// Compile the source code.Local<Script> script = Script::Compile(context, source).ToLocalChecked();// Run the script to get the result.Local<Value> result = script->Run(context).ToLocalChecked();// Convert the result to an UTF8 string and print it.
    String::Utf8Value utf8(result);printf("%s\n", *utf8);}// Dispose the isolate and tear down V8.isolate->Dispose();V8::Dispose();V8::ShutdownPlatform();delete platform;return 0;
}

 

  你可能会发现,上面说了script->Run(context) 一定要指定一个context。那么看回3.1.2 中的图3-1-3,node.cc里面的script->Run()并没有context参数。

  跳到v8的源码,deps/v8/src/api.cc,就会发现这实际上是两个重载函数,无参Script::Run()会先从Script对象取得当前的context,再调用Script::Run(Local<Context> context)。

   

图4-1-1

 


 

4.2 理解js代码如何调用C++函数 —— 运行时的上下文

  看个例子:

  左边为node 原生lib模块网络socket操作部分的文件 —— net.js,我们平时使用server.listen()时,最终调用到net.js里面,先通过new TCP()创建一个handle对象,再调用handle.listen()。而这个TCP和listen,均来自左边tcp_wrap.cc文件。

  也就是说,通过net.js里面的handle.listen()调用了tcp_wrap.cc里面的TCPWrap::Listen()函数,并且传给handle.listen()的 js参数—— backlog,被包装到了C++的 FunctionCallbackInfo<Value>类对象args。

图4-2-1 

 

  如果你第一感觉是js代码调用C++代码无法理解,那么一定是受到“语法”的干扰。

  确实,从静态的角度来看,js和C++是两种语言,语法不互通,直接在js代码调用C++函数那是不可能的。

  那么,从动态的角度(运行时)来看呢?别忘了,任何编程语言最终运行起来都不过是进程空间里的二进制代码和数据。

 

   

图 4-2-2

4.2.1 从js代码到context

  4.1 中已经讲了,Script::Compile()和Script::Run() 的时候必须为 js代码指定一个运行环境(context)。那么 js代码和context的关联是很自然的。

4.2.2 设置C++函数到context

  那么,上图蓝色标号1-5这几个步骤,即在C++代码层面,把C++函数设置到context的细节和相应的V8 接口是什么呢?

 


4.3 node的js模块调用C++模块的细节

  在node里面,在C++代码里面提供给运行时javascript代码使用的无非就是这几种:

  1. 一个对象(比如process),对象上设置属性(比如process.versions)、或者方法(比如process._kill)

  2. 函数对象(比如TCP),设置原型方法(比如TCP.prototype.listen)

4.3.1  process对象 —— V8的Object类

  在3.2中讲到,main函数启动后会加载执行src/node.js文件,并且把process对象传给node.js文件,在里面设置process.nextTick()等方法。

  那么来看看 C++如何创建一个给js使用的对象。

4.3.1.1 类型

  回去3.1.2节看一下“图3-1-3”。在LoadEnvironment() 里面执行 f->Call()调用node.js里的匿名函数时,传过去的process对象是通过env->process_object()获取的。

  env->process_object()的实现如下: 

 图 4-3-1

  这里是个宏,展开就是

inline v8::Local<v8::Object> Environment::process_object() const {return StrongPersistentToLocal(process_object_);
}

 

  那么上面标红的process_object_ 成员,定义如下:

图 4-3-2

  这里也是一个宏,展开就是

class Environment {v8::Persistent<v8::Object> process_object_;
}

  那么这里可以看到,C++里面提供给js代码的对象,就是一个v8::Object类型的对象。

4.3.1.2 设置属性或方法

  那么,v8::Object类型的对象如何在C++里面设置属性呢?

图4-3-3

  这里可以看到,v8::Object类提供了Set()方法,来让你设置供js访问的属性或方法。

 

4.3.2 TCP类 —— v8的FunctionTemplate类

  那么第二种类型,就是设置prototype方法。在js里面,没有真正的类的概念,而是通过给函数对象TCP的prototype属性设置方法,使用的时候通过new TCP()去创建实例。

  那么,v8如何设置原型方法?

4.3.2.1 设置原型方法

图4-3-4

  这里可以看到,通过创建一个v8::FunctionTemplate类型的对象 t,通过 t->PrototypeTemplate() 去获取函数对象的prototype,并进一步调用Set()去设置prototype上的方法。

  最后再通过 t->GetFunction() 去获取一个该函数模版的方法。

  

注:关于 js文件process.binding('tcp_wrap')引入TCP函数对象的机制,在下一篇博客讲。

 

转载于:https://www.cnblogs.com/papertree/p/5285705.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EasyConnect安装使用教程

easyconnect电脑版是一款为企业提供的移动信息化办公软件&#xff0c;这款软件可以让公司经常出差的人员能在公司范围外使用公司的内网系统和相关应用。软件支持移动和pc平台&#xff0c;不管是在电脑上还是手机上使用都非常方便&#xff0c;easyconnect电脑版便捷性和安全性使…

xp如何快速锁定计算机,Window XP中快速锁定计算机两法

在Windows XP时工作时&#xff0c;我们经常要锁定计算机&#xff0c;当计算机被锁定后&#xff0c;只有重新登录才能够使用计算机&#xff0c;从而保证了计算机的安全。但是&#xff0c;一般情况下我们需要锁定计算机操作时&#xff0c;都是按下CTRLALTDEL(或者为Delete)键&…

辅助判卷程序项目的扩展--自动出题

既完成了主模块---计算题目的设计后&#xff0c;我就开始了自动出题程序的设计&#xff0c;这个程序的思路比较简单&#xff0c;并不是很完美 下面是程序截图和生成的算式 题目中最多包含一对括号&#xff0c;此程序唯一的遗憾就是有时候计算结果会很大例如7736/4这样的结果 下…

javaScript实现E-mail 验证

下面的函数检查输入的数据是否符合电子邮件地址的基本语法。 意思就是说&#xff0c;输入的数据必须包含 符号和点号 (.)。同时&#xff0c; 不可以是邮件地址的首字符&#xff0c;并且 之后需有至少一个点号&#xff1a; function validateForm(){var xdocument.forms["…

电子门锁没电的解决办法

导读:今天对象回家,输入电子门锁密码怎么也打不开,指示灯也不亮,前段时间也时不时的能按,我就预感到电池没电了,那么我是如何进入家门的呢? 一般这种电子门锁可以输入密码,也可以使用机械钥匙。说实话,这钥匙在哪我压根没见过,租的房子,房东都不知道,只能输入密码才…

计算机专业常用图论,同等学力申硕计算机专业--数学公式集合(新增学习笔记)...

组合数学部分&#xff1a;基础公式&#xff1a;定义:从n个不同的元素中, 取r个并按次序排列, 称为从n中取r个的一个排列, 全部这样的排列数记为P(n, r).定义: 从n个不同的元素中, 取r个但是不考虑次序时候, 称为从n中取r个的一个组合, 全部这样的组合总数记为C(n, r).定义: 从n…

使用Ubuntu22+Minikube快速搭建K8S开发环境

安装Vmware 这一步&#xff0c;可以参考我的如下课程。 安装Ubuntu22 下载ISO镜像 这里我推荐从清华镜像源下载&#xff0c;速度会快非常多。 下载地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/22.04.3/ 如果你报名了我的这门视频课程&#xf…

linux内核分析——扒开系统调用的三层皮(上)

20135125陈智威 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 系统调用&#xff1a;库函数封装了系统调用&#xff0c;通过库函数和系统调用打交道 用户态&#xff1a;低级别执行状态&#xff0c;代码的掌控范围会受到限…

微型计算机系统中的内部寄存,微机原理与接口技术习题集汇总.doc

微机原理与接口技术习题集汇总.doc (50页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;29.9 积分&#xfeff;.word格式,第二章 微机基本组成及工作原理1.1微型机的基本结构一、单项选择题1&#xf…

10个对Web开发者最有用的Python包

Python最近成为了开发人员最喜欢的语言之一。无论你是专业的&#xff0c;业余的&#xff0c;还是一个初学者&#xff0c;你都可以从Python语言及其程序包中受益。Python已经被证明是当今最具活力的面向对象的编程语言之一。这就是为什么即使是世界顶级公司也广泛使用这种语言的…

真正释放Maven和Java EE的强大功能

如果野心和愿景太复杂而无法使用&#xff0c;那么它们可能会毁灭伟大的解决方案。 尽管Maven和Java EE是在整个Java行业中都已建立的良好技术&#xff0c;但是使用它们并使用其作者希望您使用的所有技术和模式来设计项目可能非常棘手。 在开发过程中途&#xff0c;由于一开始就…

【前端面试题】2021/3/12挺经典的面试题,这个经历很深刻。

今天面试去啦&#xff0c;填了职业性格测试&#xff0c;人格测试及招聘的基本经历信息&#xff0c;面试官是技术头头&#xff0c;柔中带钢&#xff0c;问题润物细无声的感觉&#xff0c;很考验基本功。 上午10:30面试了一个达达的前端&#xff0c;采用的是线上腾讯会议的方式&a…

html5 ios cookie,ios – WKWebView,获取所有cookie

我想从WKWebView获取所有cookie.为什么&#xff1f;我已经启动了一个使用基于Web的身份验证的项目.因此,我应该拦截cookie以确保用户已登录并用于其他目的.另一种情况 – 想象一下,如果用户登录,而不是“杀死”应用程序 – 由于存储此cookie会话的一些延迟将丢失:(.The problem…

【前端面试题】2021/3/15面试题

最近在boss直聘上投了很多简历&#xff0c;记录一下今天的面试题&#xff0c;这个好几个都是电话直接打过来问时间方便&#xff1f;我一回答方便就直接开始丢题目&#xff0c;我也不知道哪个公司的。感觉公司不是很正规的感觉&#xff0c;感觉那边有个问题题库&#xff0c;面试…

javafx打包路径问题_关于JavaFX的最常见问题

javafx打包路径问题上周&#xff0c;我在斯德哥尔摩的Jfokus 2012上做了一个关于JavaFX的演讲&#xff0c;当时我意识到每次活动都会问三个问题。 似乎有一个普遍的兴趣&#xff0c;所以我尝试在这篇文章中回答他们&#xff08;尽可能的说实话&#xff09;&#xff1a; iPad或其…

【前端面试题】关于一些js的一些面试题(金融行业),我和面试官扯了三个小时

今天去面试了一家金融公司&#xff0c;招聘比较着急&#xff0c;一面后直接二面等结果&#xff0c;这种公司一般对js要求比较高&#xff0c;笔试题基本都是js相关的题&#xff0c;针对公司的客户要求也会做一些jquery,vue.react相关的插件&#xff0c;H5及webAPP。下面直接说题…

上海大学计算机学院客座教授,刘云虹教授受聘上海大学外国语学院客座教授并做学术讲座...

11月29日14:00&#xff0c;南京大学外国语学院副院长、博士生导师刘云虹教授被我院聘为客座教授并做主题为《中国文学外译与翻译历史观》的学术讲座。学院副院长苗福光教授主持&#xff0c;副院长邓志勇教授(主持工作)为刘教授颁发了聘书。讲座从刘教授自己的学术研究领域和起点…

安徽阜阳计算机高中学校排名,安徽阜阳排名靠前的三大高中,有争议?2020年高考成绩说话!...

安徽省阜阳市&#xff0c;古称汝阴&#xff0c;阜阳历史悠久、文化璀璨、人才辈出&#xff0c;有阜阳剪纸等国家非物质文化遗产&#xff0c;也是管仲、鲍叔牙等历史名人的故乡&#xff1b;阜阳风景秀丽&#xff0c;辖区内有诸多知名景点&#xff0c;其中八里河风景区为国家AAAA…

数组练习2

结对开发&#xff1a;张哲 张晓菲 题目&#xff1a;返回一个数组中子数组最大和&#xff0c;数组可以首尾相连。 一、实验思路 本次实验在第一次的基础上增加了一些难度&#xff0c;数组可以首尾相连组成一个环&#xff0c;我们两个经过思考和讨论后得到一个方法&#xff1a; …

Java 8中最快的垃圾收集器是什么?

OpenJDK 8具有几种垃圾收集器算法&#xff0c;例如Parallel GC &#xff0c; CMS和G1 。 哪一个最快&#xff1f; 如果默认的GC从Java 8中的并行GC更改为Java 9中的G1&#xff08;当前建议&#xff09;&#xff0c;将会发生什么&#xff1f; 让我们对其进行基准测试。 基准方法…