运行 c/c++ 来自 nodejs 的代码

Run c/c++ code from nodejs

假设我有一个简单的 c++ 或 c 语言的 hello world 文件(任何可以帮助我在 node.js 中更轻松地使用它的东西,最好是 c)并且想要 运行 它来自 node.js 文件。考虑到该文件将用于提高性能,最有效的方法是什么(将 CPU 密集函数从 node.js 更改为 c/c++)。

我遇到了 addons 但在我看来,为了使用它,我必须转换大量代码才能将其转换为该格式。有没有更简单的方法?

对于我在 C++ 中编写的图像分割算法,我需要帮助 full-stack 开发人员包装 node.js 的共享库。据我所知,从 Google 的一天开始,黑入 node.js,这对我来说是一个有点陌生的世界,有两个主要选择:

  1. 使用node-ffi,或者,
  2. addons正如你所说。

对于上面的1,你不需要做太多。您只需要在 node.js 中要求 ffirefref-array packages/addons 即可调用应用程序代码的 C API .我遵循了一些 nice tutorial,这帮助我在 15 分钟内开始。

但是最终我们的项目需要选择上面的2。这是因为我们的 full-stack 开发人员依赖其他一些需要最新版本 node.js 的插件。显然,当我们查看 node-ffi 的问题板时,截至此答案发布时间,它 支持 v9.x 家族 node.js。因此,我采用了原生插件的方式。我花了大约 4 个小时来理解和编写代码。我不确定这是否是最 convenient/efficient 可能的方式,但我所做的是

  1. 使用buffers分配内存在node.js,
  2. 使用 node.js 中的 nan 编写一个简单的插件,reinterpret_castnode.jschar* 缓冲区并调用完全相同的 C API 我们的共享库,最后,
  3. link 针对我们使用 binding.gyp.
  4. 创建的共享库

显然,用户应该使用 Node.js(又名 nan)的本机抽象,以避免需要处理 v8 中引入的重大更改。我找到了另一个nice tutorial,它帮助我轻松解决了问题。

最后,Scott Frees' blog site seems to have a lot of self-contained articles/examples for those who would like to go deeper. He also argues 在哪些情况下您应该更喜欢一种方法而不是另一种方法(例如 node-ffi 而不是原生插件)。基本上,我的理解是编写本机插件会更有效率,即使对于我们的应用程序来说这并不重要。 node-ffi 也给出了令人满意的行为,因为我们正在解决一个图像分割问题(​​无论如何它比调用开销花费更多的时间)。

所以,简而言之,

I came across the addons but it seems to me, that in order to use it I'll have to convert a lot of code to bring it to that format.

嗯,不一定!这取决于您愿意实现的目标。它可以像为特定 C-API 共享库编译 C++ 代码一样简单,然后在 nan 中编写一个 20 行的包装器,它基本上为 in-place 做了一些 reinterpret_cast ] 内存操作,最后 linking 对 binding.gyp.

中的库

Is there an easier way?

是的,有。 node-ffi可以在半小时内帮你解决问题。但是,它 可能 对你的场景来说不是最有效的,或者它 可能 对你来说不是一个可行的选择,因为它目前不与 node.js.

v9.x 家族一起构建

我不明白为什么使用 child_process 会比其他选项慢, 我推荐:

// myCFile.c
#include <stdio.h>
int main(void){

    // processor intensive computations
    int x = 1+2+3;

    // send to node via stdout
    printf("%d", x);

    //terminate the process
    return 0;
}

编译:

$ gcc -o myExecutable myCFile.c

并像这样使用 child_process:

//myNodeFile.js
const { exec } = require("child_process");
exec("./myExecutable", (error, stdout, stderr) => console.log(stdout));