返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >用C/C++来实现 Node.js 的模块(一)
  • 658
分享到

用C/C++来实现 Node.js 的模块(一)

来实现模块Node 2022-06-04 17:06:14 658人浏览 八月长安
摘要

 N久之前的一个坑——用 node.js 来重构 NBUT 的 Online Judge,包括评测端也得重构一遍。(至于什么时候完成大家就不要关心了,(/?Д′)/~ ??   总之我们现在要做的其实简而言

 N久之前的一个坑——用 node.js 来重构 NBUT 的 Online Judge,包括评测端也得重构一遍。(至于什么时候完成大家就不要关心了,(/?Д′)/~ ??

  总之我们现在要做的其实简而言之就是——用C/C++来实现 node.js 的模块。

准备工作

  工欲善其事,必先~~耍流氓~~利其器。

node-gyp

  首先你需要一个 node-gyp 模块。

  在任意角落,执行:

$ npm install node-gyp -g

  在进行一系列的 blahblah 之后,你就安装好了。

python

  然后你需要有个 Python 环境。

  自己去官网搞一个来。


注意: 根据 node-gyp 的GitHub显示,请务必保证你的 python 版本介于 2.5.0 和 3.0.0 之间。

编译环境

  嘛嘛,我就偷懒点不细写了,还请自己移步到 node-gyp 去看编译器的需求。并且倒腾好。

入门

  我就拿官网的入门 Hello World说事儿了。

Hello World

  请准备一个 c++ 文件,比如就叫 ~~sb.cc~~ hello.cc。

  然后我们一步步来,先往里面搞出头文件和定义好命名空间:

#include <node.h>

#include <v8.h>

using namespace v8;

主要函数

  接下去我们写一个函数,其返回值是 Handle<Value>。

Handle<Value> Hello(const Arguments& args)

{

    //... 嗷嗷待写

}

  然后我来粗粗解析一下这些东西:

Handle<Value>

  做人要有节操,我事先申明我是从这里(@fool)参考的。


V8 里使用 Handle 类型来托管 javascript 对象,与 C++ 的 std::sharedpointer 类似,Handle 类型间的赋值均是直接传递对象引用,但不同的是,V8 使用自己的 GC 来管理对象生命周期,而不是智能指针常用的引用计数。

JavaScript 类型在 C++ 中均有对应的自定义类型,如 String 、 Integer 、 Object 、 Date 、 Array 等,严格遵守在 JavaScript 中的继承关系。 C++ 中使用这些类型时,必须使用 Handle 托管,以使用 GC 来管理它们的生命周期,而不使用原生栈和堆。

  而这个所谓的 Value ,从 V8 引擎的头文件 v8.h 中的各种继承关系中可以看出来,其实就是 JavaScript 中各种对象的基类。

  在了解了这件事之后,我们大致能明白上面那段函数的申明的意思就是说,我们写一个 Hello 函数,其返回的是一个不定类型的值。


注意: 我们只能返回特定的类型,即在 Handle 托管下的 String 啊 Integer 啊等等等等。

Arguments

  这个就是传入这个函数的参数了。我们都知道在 Node.js 中,参数个数是乱来的。而这些参数传进去到 C++ 中的时候,就转变成了这个 Arguments 类型的对象了。

  具体的用法我们在后面再说,在这里只需要明白这个是个什么东西就好。(为毛要卖关子?因为 Node.js 官方文档中的例子就是分开来讲的,我现在只是讲第一个 Hello World 的例子而已( ´థ౪థ)σ

添砖加瓦

  接下去我们就开始添砖加瓦了。就最简单的两句话:

Handle<Value> Hello(const Arguments& args)

{

    HandleScope scope;

    return scope.Close(String::New("world"));

}

  这两句话是什么意思呢?大致的意思就是返回一个 Node.js 中的字符串 "world"。

HandleScope

  同参考自这里。


Handle 的生命周期和 C++ 智能指针不同,并不是在 C++ 语义的 scope 内生存(即{} 包围的部分),而需要通过 HandleScope 手动指定。HandleScope 只能分配在栈上,HandleScope 对象声明后,其后建立的 Handle 都由 HandleScope 来管理生命周期,HandleScope 对象析构后,其管理的 Handle 将由 GC 判断是否回收。

  所以呢,我们得在需要管理他的生命周期的时候申明这个 Scope 。好的,那么为什么我们的代码不这么写呢?

Handle<Value> Hello(const Arguments& args)

{

    HandleScope scope;

    return String::New("world");

}

  因为当函数返回时,scope 会被析构,其管理的Handle也都将被回收,所以这个 String 就会变得没有意义。

  所以呢 V8 就想出了个神奇的点子——HandleScope::Close(Handle<T> Value) 函数!这个函数的用处就是关闭这个 Scope 并且把里面的参数转交给上一个 Scope 管理,也就是进入这个函数前的 Scope。

  于是就有了我们之前的代码 scope.Close(String::New("world"));。

String::New

  这个 String 类所对应的就是 Node.js 中原生的字符串类。继承自 Value 类。与此类似,还有:

•Array
•Integer
•Boolean
•Object
•Date
•Number
•Function
•...

  这些东西有些是继承自 Value,有些是二次继承。我们这里就不多做研究,自己可以看看 V8 的代码(至少是头文件)研究研究或者看看这个手册。

  而这个 New 呢?这里可以看的。就是新建一个 String 对象。

  至此,这个主要函数我们就解析完毕了。

导出对象

  我们来温习一下,如果是在 Node.js 里面写的话,我们怎么导出函数或者对象什么的呢?

exports.hello = function() {}

  那么,在 C++ 中我们该如何做到这一步呢?

初始化函数

  首先,我们写个初始化函数:

void init(Handle<Object> exports)

{

    //... 嗷嗷待写你妹啊!#゚Å゚)⊂彡☆))゚Д゚)・∵

}

  这是龟腚!函数名什么的无所谓,但是传入的参数一定是一个 Handle<Object>,代表我们下面将要在这货上导出东西。

  然后,我们就在这里面写上导出的东西了:

void init(Handle<Object> exports)

{

    exports->Set(String::NewSymbol("hello"),

        FunctionTemplate::New(Hello)->GetFunction());

}

  大致的意思就是说,为这个 exports 对象添加一个字段叫 hello,所对应的东西是一个函数,而这个函数就是我们亲爱的 Hello 函数了。

  用伪代码写直白点就是:

void init(Handle<Object> exports)

{

    exports.Set("hello", function hello);

}

  大功告成!

  (大功告成你妹啊!闭嘴( ‘д‘⊂彡☆))Д´)

真·导出

  这才是最后一步,我们最后要申明,这个就是导出的入口,所以我们在代码的末尾加上这一行:
NODE_MODULE(hello, init)

  纳了个尼?!这又是什么东西?

  别着急,这个 NODE_MODULE 是一个宏,它的意思呢就是说我们采用 init 这个初始化函数来把要导出的东西导出到 hello 中。那么这个 hello 哪来呢?

  它来自文件名!对,没错,它来自文件名。你并不需要事先申明它,你也不必担心不能用,总之你的这个最终编译好的二进制文件名叫什么,这里的 hello 你就填什么,当然要除去后缀名了。

  详见官方文档。


Note that all Node addons must export an initialization function:

void Initialize (Handle<Object> exports);

NODE_MODULE(module_name, Initialize)

There is no semi-colon after NODE_MODULE as it's not a function (see node.h).

The module_name needs to match the filename of the final binary (minus the .node suffix).

编译 (๑•́ ₃ •̀๑)

  来吧,让我们一起编译吧!

  我们再新建一个类似于 Makefile 的归档文件吧——binding.gyp。

  并且在里面添加这样的代码:

{

  "targets": [

    {

      "target_name": "hello",

      "sources": [ "hello.cc" ]

    }

  ]

}

  为什么这么写呢?可以参考 node-gyp 的官方文档。

configure

  在文件搞好之后,我们要在这个目录下面执行这个命令了:

$ node-gyp configure

  如果一切正常的话,应该会生成一个 build 的目录,然后里面有相关文件,也许是 M$ Visual Studio 的 vcxproj 文件等,也许是 Makefile ,视平台而定。

build

  Makefile 也生成好之后,我们就开始构造编译了:
$ node-gyp build

  等到一切编译完成,才算是真正的大功告成了!不信你去看看 build/Release 目录,下面是不是有一个 hello.node 文件了?没错,这个就是 C++ 等下要给 Node.js 捡的肥皂!

搞基吧!Node ?(✿゚?゚)ノ C++

  我们在刚才那个目录下新建一个文件 jianfeizao.js:

var addon = require("./build/Release/hello");

console.log(addon.hello());

  看到没!看到没!出来了出来了!Node.js 和 C++ 搞基的结果!这个 addon.hello() 就是我们之前在 C++ 代码中写的 Handle<Value> Hello(const Arguments& args) 了,我们现在就已经把它返回的值给输出了。

洗洗睡吧,下节更深入

  时间不早了,今天就写到这里了,至此为止大家都能搞出最基础的 Hello world 的 C++ 扩展了吧。下一次写的应该会更深入一点,至于下一次是什么时候,我也不知道啦其实。
  (喂喂喂,撸主怎么可以这么不负责!(o゚ロ゚)┌┛Σ(ノ´ω`)ノ

--结束END--

本文标题: 用C/C++来实现 Node.js 的模块(一)

本文链接: https://lsjlt.com/news/11991.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 用C/C++来实现 Node.js 的模块(一)
     N久之前的一个坑——用 Node.js 来重构 NBUT 的 Online Judge,包括评测端也得重构一遍。(至于什么时候完成大家就不要关心了,(/Д′)/~   总之我们现在要做的其实简而言之就是...
    99+
    2022-06-04
    来实现 模块 Node
  • 用C/C++来实现 Node.js 的模块(二)
    温故而知新,可以为湿矣   首先请大家记住这个 V8 的在线手册——http://izs.me/v8-docs/main.html。   还记得上次的 building.gyp 文件吗? { "ta...
    99+
    2022-06-04
    来实现 模块 Node
  • node.js调用C++开发的模块实例
    如何用C++和node交互,在node的程序中,如果有大数据量的计算,处理起来比较慢,可以用C++来处理,然后通过回调(callback的形式),返回给node。先回顾一下正统的用 C++ 开发 nativ...
    99+
    2022-06-04
    实例 模块 node
  • 如何使用C/C++编写node.js原生模块
    这篇文章主要为大家展示了“如何使用C/C++编写node.js原生模块”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用C/C++编写node.js原生模块...
    99+
    2024-04-02
  • 怎么使用C/C++编写node.js原生模块
    这篇文章主要讲解了“怎么使用C/C++编写node.js原生模块”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用C/C++编写node.js原生模块”吧!Hello World不能免俗...
    99+
    2023-06-17
  • 使用C++为node.js写扩展模块
    前提: 安装好node.js、Python2.7与visual studio 2013。 过程: 首先安装GYP项目生成工具,npm install -g node-gyp 。 建立test目录,这是我们的...
    99+
    2022-06-04
    模块 node js
  • 利用C/C++编写node.js原生模块的方法教程
    前言 一直想了解一下使用C/C++编写nodejs原生模块,从网上找到的博客,大多都停留在如何搭建环境,然后一个Hello World完事。连更多的参考资料也没有。于是就自己整理了一下,分享于此。 至于准备...
    99+
    2022-06-04
    模块 方法 教程
  • 怎么用C++编写node.js原生模块
    本篇内容主要讲解“怎么用C++编写node.js原生模块”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用C++编写node.js原生模块”吧!Hello World不能免俗,第一个先上来写个...
    99+
    2023-07-04
  • Node.js中怎么实现一个模块系统
    Node.js中怎么实现一个模块系统,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Node.js模块系统为了让Node.js的文件可以相互...
    99+
    2024-04-02
  • C#实现学生模块的增删改查
    本文实例为大家分享了C#实现学生模块的增删改查的具体代码,供大家参考,具体内容如下 using System; using System.Collections.Generic; ...
    99+
    2024-04-02
  • Node.js用readline模块实现输入输出
    什么是Readline Readline是Node.js里实现标准输入输出的封装好的模块,通过这个模块我们可以以逐行的方式读取数据流。使用require("readline")可以引用模块。 如何使用Re...
    99+
    2022-06-04
    输入输出 模块 Node
  • C++超集C++/CLI模块的基本用法
    C#和C++是非常相似的两种语言,然而我们却常常将其用于两种不同的地方,C#得益于其简洁的语法和丰富的类库,常用来构建业务系统。C++则具有底层API的访问能力和拔尖的执行效率,往往...
    99+
    2024-04-02
  • Node.js里面的内置模块和自定义模块的实现
    一、Commonjs Commonjs是nodejs中的自定义模块 Commonjs规范的提出,弥补javascript没有标准的缺陷,提供一个类似后端语言的标准...
    99+
    2024-04-02
  • 模块使用:time、datetime、c
    ## time:时间 时间戳(timestamp):time.time() 延迟线程的运行:time.sleep(secs) (指定时间戳下的)当前时区时间:time.localtime([secs]) (指定时间戳下的)格林威治时间:...
    99+
    2023-01-31
    模块 time datetime
  • 为 Python 写一个 C++ 扩展模块
    使用 C 扩展为 Python 提供特定功能。在前一篇文章中,我介绍了 ​​六个 Python 解释器​​。在大多数系统上,CPython 是默认的解释器,而且根据民意调查显示,它还是最流行的解释器。Cpython 的独有功能是使用扩展 A...
    99+
    2023-05-14
    Python 模块 C++
  • Node.js Exports 对象:模块化设计的未来
    exports 对象的运作原理 exports 对象是一个全局对象,在每个模块中都可用。当模块导出一个值时,它会被附加到 exports 对象上。导入模块时,将获取 exports 对象并访问其属性以获取导出的值。 在以下示例中,modu...
    99+
    2024-04-02
  • 一起来学习C#的观察者模式
    using System; using System.Collections.Generic; public class Example { public static vo...
    99+
    2024-04-02
  • python模块与C和C++动态库相互调用实现过程示例
    目录Python调用C/C++1、Python调用C动态链接库C语言文件:pycall.cgcc编译生成动态库libpycall.soPython调用动态库的文件:pycall.py...
    99+
    2024-04-02
  • Node.js里面的内置模块和自定义模块的实现方法
    这篇文章将为大家详细讲解有关Node.js里面的内置模块和自定义模块的实现方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、CommonjsCommonjs是nodejs中的自定义模块Commonjs...
    99+
    2023-06-15
  • C语言代码 模块化实现三子棋
    目录主函数(test.c文件)游戏开始界面设计游戏运行逻辑(不具体解释函数的实现)头文件(game.h)及游戏函数文件(game.c)初始化空棋盘函数棋盘打印函数玩家下棋函数电脑下棋...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作