node-ffi与节点扩展以访问现有的C ++function

我有一些现有的C ++代码在独立的C ++应用程序中进行数字处理。 我现在想在新的node.js应用程序中使用该代码。

研究如何从node.js访问C ++代码,有两个选项:

  1. 编写一个node.js扩展
  2. 使用node-ffi

节点ffi似乎是一个很好的select来访问现有的 ,但我正确的想法,如果我使用node-ffi我将不得不写一个C封装,使我的C ++可访问? (这是我可以通过Visual Studio在Windows上运行的简单testing用例的唯一方法)。

对于我的情况,我的源代码已经在C ++中,而不是C,在上面两个选项之间进行select时需要考虑什么?

FFI与dynamicC库一起工作。 这意味着您必须从外部公开您的dynamic库。 在C ++中,你用extern“C”来完成这个工作,如下所示:

#ifdef __cplusplus extern "C" { #endif int foo (int param){ int ret = 0; // do C++ things return ret; } int bar(){ int ret = 0; // do C++ things return ret; } #ifdef __cplusplus } #endif 

这将使您的C ++函数对C事物可用,作为dynamic库方法。

在你将C ++库编译为libmylibrary.dll / .so之后,以下是你如何用javascript包装这个东西:

 var ffi = require('ffi'); var mylibrary = ffi.Library('libmylibrary', { "foo": [ "int", ["int"] ], "bar": [ "int", [] ] }); 

有很多更酷的事情,你可以做。 看看, 在这里

如果这是一个节点库,只需将你的方法放在module.exports中。 以下是上述C ++代码的一个完整示例,包含同步和asynchronous方法:

 var ffi = require('ffi'); var mylibrary = ffi.Library('libmylibrary', { "foo": [ "int", ["int"] ], "bar": [ "int", [] ] }); module.exports = { fooSync : mylibrary.foo, foo: mylibrary.foo.async, barSync : mylibrary.bar, bar: mylibrary.bar.async }; 

我没有使用node-ffi-generate ,但是为你生成这些types的包装看起来很酷。

如果我把这个文件保存为mylibrary.js,我可以像这样使用它:

 var mylib = require('./mylibrary.js'); var num = mylib.fooSync(1); // or mylib.foo(1, function(er, num){ }); 

至于“是不是更好?”的问题 我想是的,对于大多数事情。 如果你把你的方法做成extern C,那么他们就会用其他语言工作,其中一些语言也有FFI,所以你可以用任何你的目标语言来编写上面简单的等价语言。 这意味着除了基本的“加载C ++库”以外,还有很less的代码需要维护,而且“混淆了它的签名以适应X语言”。 这不是特定于节点。 另外一个好处就是共享共享库(比如在教程中给出的sqlite)。你可能并不关心他们拥有什么版本,或者想用更多的C ++代码来包装它,需要编译才能使用它。 使用FFI,你可以用JavaScript来包装一个预编译/安装的库。