【问题标题】:How can I use a C++ library from node.js?如何使用 node.js 中的 C++ 库?
【发布时间】:2016-04-06 07:24:01
【问题描述】:

如何使用 node.js 中的 C++ 库?

【问题讨论】:

标签: javascript c++ node.js binding


【解决方案1】:

尝试shelljs 使用来自 linux/unix 的节点程序调用 c/c++ 程序或共享库。 node-cmd Windows 中的一个选项。这两个包基本上使我们能够调用 c/c++ 程序,类似于我们从终端/命令行调用的方式。

例如在 ubuntu 中:

const shell = require('shelljs');

shell.exec("command or script name");

在窗口中:

const cmd = require('node-cmd');
cmd.run('command here');

注意:shelljs 和 node-cmd 用于运行 os 命令,不特定于 c/c++。

【讨论】:

    【解决方案2】:

    这是Getting your C++ to the Web with Node.js上的一篇有趣的文章

    将 C++ 代码与 Node.js 应用程序集成的三种通用方法 - 虽然每个类别都有很多变化:

    1. 自动化 - 在子进程中将 C++ 作为独立应用调用。
    2. 共享库 - 将您的 C++ 例程打包到一个共享库 (dll) 中,并直接从 Node.js 调用这些例程。
    3. Node.js 插件 - 将您的 C++ 代码编译为原生 Node.js 模块/插件。

    【讨论】:

      【解决方案3】:

      小心 swig 和 C++: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

      不建议在 C++ 源文件(会出现在 .C 或 .cxx 文件中的文件)上运行 SWIG。即使 SWIG 可以解析 C++ 类声明,它也会忽略与其原始类定义分离的声明(解析声明,但可能会生成大量警告消息)。例如:

      /* Not supported by SWIG */
      int foo::bar(int) {
          ... whatever ...
      }
      

      很少有 C++ 类仅限于一个 .h 文件。

      另外,swig 支持 JavaScript 的版本是 swig-3.0.1 或更高版本。

      【讨论】:

      • 我不明白 SWIG 会如何处理 foo::bar 的定义。类成员的定义都是关于实现的; SWIG 生成的包装器都是关于接口的。
      【解决方案4】:

      有更新的方式连接 Node.js 和 C++。请在Nan抢劫。

      编辑 最快最简单的方法是nbind。如果你想编写异步插件,你可以结合 nan 的 Asyncworker 类。

      【讨论】:

        【解决方案5】:

        这个问题现在有了新的答案。 SWIG,从 3.0 版开始,似乎为 Node.js、Webkit 和 v8 提供了 javascript interface generators。

        一段时间以来,我一直在将 SWIG 广泛用于 Java 和 Python,一旦您了解 SWIG 的工作原理,将 C++ 代码与SWIG 支持的语言。

        举个小例子,假设你有一个带有 myclass.h 头文件的库:

        #include<iostream>
        
        class MyClass {
                int myNumber;
        public:
                MyClass(int number): myNumber(number){}
                void sayHello() {
                        std::cout << "Hello, my number is:" 
                        << myNumber <<std::endl;
                }
        };
        

        为了在 node 中使用这个类,你只需编写以下 SWIG 接口文件(mylib.i):

        %module "mylib"
        %{
        #include "myclass.h"
        %}
        %include "myclass.h"
        

        创建绑定文件binding.gyp:

        {
          "targets": [
            {
              "target_name": "mylib",
              "sources": [ "mylib_wrap.cxx" ]
            }
          ]
        }
        

        运行以下命令:

        swig -c++ -javascript -node mylib.i
        node-gyp build
        

        现在,从同一个文件夹运行节点,你可以这样做:

        > var mylib = require("./build/Release/mylib")
        > var c = new mylib.MyClass(5)
        > c.sayHello()
        Hello, my number is:5
        

        即使我们需要为这样一个小示例编写 2 个接口文件,请注意我们不必在任何地方提及 MyClass 构造函数或 sayHello 方法,SWIG 发现了这些东西,并自动生成自然接口.

        【讨论】:

        • 在玩了 swig/node.js 之后,似乎 swig 无法处理返回数组的 C++ 函数(更准确地说:返回数组指针的函数)。也就是说,您似乎无法在 C++ 中构建一个返回类似 JavaScript 数组的函数并让 swig 自动为您转换它。
        • @George SWIG 确实是一个了不起的工具,但它不是魔法,也不是一些通用的 AI 可以理解 C++ 代码的语义并生成相应的接口。请注意 C++ 和 javascript 的语义、所有权概念和生命周期管理有何根本不同。
        • 因此,您可以通过两种方式查看 SWIG:它是一种工具,可以开箱即用地做它可以做的事情,并遵守其规则。这意味着,您不应该期望从返回数组的 C++ 函数中弹出 javascript 数组。您可以做的是将您的函数包装在 C++ 中,以便它返回一个行为类似于数组的对象(例如,std::vector&lt;&gt;,只是 %include "std_vector.i"),您将能够在 javascript 端操作它有点尴尬的方式。请注意,这种方法仍然比自己编写 FFI 更容易、更安全。
        • 使用 SWIG 的另一种方式是了解底层机制。花几个月的时间使用它,深入了解它的功能。然后你可以让它生成你想要的界面。您希望它为 C++ 数组返回一个 javascript 数组,很好,您可以这样做,但您应该首先学习如何在这样的接口中表达您期望的确切语义,并确保它很好地映射到您的问题域。
        • 无论哪种方式,我建议您从第一种方法开始,并在此过程中完善您对 SWIG 的使用。研究 SWIG 对您的代码做了什么以及如何操作它是非常鼓舞人心的。
        【解决方案6】:

        你可以使用emscripten将C++代码编译成js。

        【讨论】:

        • 如果 OP 的目标是获得编译后的 C++ 的性能优势,那么这将是一个坏主意,并且因为迂腐而无法回答问题。
        • @Greg 但它仍然是一个值得考虑的想法。人们来到这个页面是为了手头的各种类型的项目。当您拥有 C/C++ 代码库并且只想在 Nodejs 中使用它时,我认为 Emscripten 是一个不错的选择。
        • - 如果 OP 的目标是获得编译后的 C++ 的性能优势 - emscripten 的一些优势,尤其是 WASM:没有 GC 开销、更少的解析和 JIT开销、本机整数、AOT 优化。
        【解决方案7】:

        看node-ffi。

        node-ffi 是一个 Node.js 插件,用于使用纯 JavaScript 加载和调用动态库。它可用于创建与本机库的绑定,而无需编写任何 C++ 代码。

        【讨论】:

        • 不同的 C++ 编译器会创建不同的 ABI,因此要使用 node-ffi,您可能必须使用 C 接口包装您的 C++ 代码 - 或者至少我这样做是为了在 Windows 上使用 Visual Studio 进行工作。有关如何执行此操作的详细信息,请参阅stackoverflow.com/questions/2045774/…。或者我应该能够在没有包装器的情况下在 C++ 上使用 node-ffi?
        • 我知道这个 cmets 已经一年多了,但是......是否可以在没有 C 包装器的情况下使用 C++ 库?
        • 我遇到了 VS 2017/2019 的 node-ffi 编译问题。这是一个主要的PITA!它是依赖于 Python 2.7 还是仅仅是构建过程? NodeJS中必须有一个标准Win32 DLL的LoadLibrary机制?
        • node-ffi 不再受支持且无法无缝编译,不推荐。
        【解决方案8】:

        您可以使用 node.js 扩展来为您的 C++ 代码提供绑定。这是一个涵盖该内容的教程:

        http://syskall.com/how-to-write-your-own-native-nodejs-extension

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-02
          • 1970-01-01
          相关资源
          最近更新 更多