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


Answers:


66

看一下node-ffi

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


5
不同的C ++编译器会创建不同的ABI,因此要使用node-ffi,您可能必须使用C接口包装C ++代码-或至少我确实做到了在Windows与Visual Studio上工作。有关如何执行此操作的详细信息,请参见stackoverflow.com/questions/2045774/…。还是无需包装就可以在C ++上使用node-ffi?
煎饼

1
我知道距此评论已经一年多了,但是...是否可以在没有C包装程序的情况下使用C ++库?
Miki de Arcayne

我遇到了Node-ffi的VS 2017/2019编译问题。这是主要的PITA!是依赖于Python 2.7还是仅仅是构建过程?对于标准Win32 DLL,NodeJS中必须有LoadLibrary机制吗?
tgraupmann

78

现在对该问题有了新的答案。从版本3.0开始,SWIG似乎为Node.js,Webkit和v8 提供了JavaScript接口生成器

我已经在Java和Python上广泛使用SWIG一段时间了,一旦您了解SWIG的工作原理,就几乎不需要花力气(相比于ffi或目标语言中的等效语言)将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;
        }
};

为了在节点中使用此类,您只需编写以下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个接口文件,也请注意我们不必MyClasssayHello任何地方提及构造函数或方法,SWIG会发现这些内容并自动生成自然接口。


2
在使用swig / node.js玩了一段时间之后,看来swig无法处理返回数组的C ++函数(更准确地说是:返回指向数组的指针的函数)。也就是说,似乎您无法在C ++中构建一个函数,该函数返回类似JavaScript数组的内容,而swig会自动为您转换它。
乔治

5
@George SWIG确实是一个了不起的工具,但这并不是魔术,不是可以理解C ++代码的语义并生成相应接口的通用AI。请注意C ++和javascript的语义,所有权概念和生命周期管理有根本的不同。
enobayram

3
因此,您可以通过两种方式查看SWIG:该工具可以立即执行其所能做的事情,并且可以按其规则进行操作。这意味着,您不应期望看到javascript数组从返回数组的C ++函数中弹出。相反,您可以做的是将函数包装在C ++中,以便它返回一个行为类似于数组的对象(std::vector<>例如,just %include "std_vector.i"),并且您可以在javascript方面以某种尴尬的方式对其进行操作。请注意,与您自己编写FFI相比,此方法仍然更容易,更安全。
enobayram

3
您可以使用SWIG的另一种方法是了解下面的机械。花几个月使用它,深入了解它的功能。然后,您可以使其生成所需的界面。您希望它返回一个C ++数组的javascript数组,可以,但是您应该首先学习如何在这样的接口中表达期望的确切语义,并确保它很好地映射到您的问题域。
enobayram

3
无论哪种方式,我都建议您从第一种方法开始,然后逐步完善SWIG的用法。研究SWIG对您的代码的作用以及如何操作它是非常鼓舞人心的。
enobayram


11

您可以使用emscripten将C ++代码编译为js。


16
如果OP的目标是获得编译后的C ++的性能优势,并且过于花哨,它不能回答问题,那么这将是一个坏主意。
格雷格

7
@Greg,但这仍然是一个值得考虑的想法。人们来到此页面进行各种类型的项目。当您拥有C / C ++代码库并且只想在Node.js中使用它时,我认为Emscripten是一个不错的选择。
AlexStack

1
- 如果OP的目标是获得经过编译的C ++的性能好处 -一些好处可以随脚本一起转换,尤其是对于WASM:无GC开销,较少的解析和JIT开销,本机整数,AOT优化。
ArtemGr

2

有更新的方法可以连接Node.js和C ++。请在抢劫。

编辑 最快,最简单的方法是nbind。如果要编写异步加载项,可以组合Asyncworkernan的类。


1

这是一篇有关通过Node.js将C ++投入网络的有趣文章。

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

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

0

谨记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文件。

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


foo::bar无论如何,我不知道SWIG将如何处理。类成员的定义全与实现有关。SWIG生成的包装都与接口有关。
enobayram
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.