前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【nodejs每日一讲】js调用c++以及c++调用libuv的过程【慎点】

【nodejs每日一讲】js调用c++以及c++调用libuv的过程【慎点】

作者头像
theanarkh
发布2021-01-12 14:42:34
2.2K0
发布2021-01-12 14:42:34
举报
文章被收录于专栏:原创分享原创分享

1 c++模块的注册和使用

我们知道nodejs是由js、c++、c组成的。今天我们来看一下他们是如何分工和合作的。本文以net模块为例进行分析。我们可以通过以下方式使用net模块。

代码语言:javascript
复制
const net = require('net');

net模块是原生的js模块。对应nodejs源码的net.js。他是对tcp和pipe的封装,我们这里只讲tcp的功能。我们可以通过以下代码创建一个tcp服务器。

代码语言:javascript
复制
const net = require('net');
net.createServer((socket) => {}).listen(80);

我们知道js里是没有网络功能的,这就意味着,网络功能是由nodejs中的c++模块实现的。所以这时候nodejs就会创建一个c++对象。

代码语言:javascript
复制
const {
  TCP,
} = internalBinding('tcp_wrap');
new TCP(TCPConstants.SERVER);

TCP对象封装了底层tcp的功能。他对应的是c++层的tcp_wrap模块。我们看看tcp_wrap模块的代码。在分析tcp_wrap之前我们先看看internalBinding做了什么事情。

代码语言:javascript
复制
let internalBinding;
{
  const bindingObj = ObjectCreate(null);
  internalBinding = function internalBinding(module) {
    let mod = bindingObj[module];
    if (typeof mod !== 'object') {
      mod = bindingObj[module] = getInternalBinding(module);
    }
    return mod;
  };
}

internalBinding是在getInternalBinding的基础上加了缓存处理。我们继续看getInternalBinding。

代码语言:javascript
复制
// 根据模块名查找对应的模块
void GetInternalBinding(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  // 模块名
  Local<String> module = args[0].As<String>();
  node::Utf8Value module_v(env->isolate(), module);
  Local<Object> exports;
  // 查找名字为module_v并且标记位NM_F_INTERNAL的模块
  node_module* mod = FindModule(modlist_internal, *module_v, NM_F_INTERNAL);
  exports = InitModule(env, mod, module);
  args.GetReturnValue().Set(exports);
}

getInternalBinding通过模块名从模块链表里找到对应的节点。然后执行对应的初始化函数。

代码语言:javascript
复制
// 初始化一个模块,即执行他里面的注册函数
static Local<Object> InitModule(Environment* env,
                                node_module* mod,
                                Local<String> module) {
  Local<Object> exports = Object::New(env->isolate());
  Local<Value> unused = Undefined(env->isolate());
  mod->nm_context_register_func(exports, unused, env->context(), mod->nm_priv);
  return exports;
}

那么链表中的模块是从哪里来的呢?这时候我们就可以回头分析tcp_wrap了。tcp_wrap.cc的最后一句是(Initialize函数即上面的nm_context_register_func属性的值)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档