用于访问现有c++功能的node-ffi与node扩展

node-ffi vs. node extension for accessing existing C++ functionality

本文关键字:node-ffi node 扩展 功能 访问 c++ 用于      更新时间:2023-10-16

我有一些现有的c++代码,可以在一个独立的c++应用程序中进行数值处理。现在我想在一个新的node.js应用程序中使用这些代码。

研究如何从node.js访问c++代码,出现了两个选项:

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

node-ffi似乎是访问现有库的好选择,但我是否认为如果我使用node-ffi,我将不得不编写一个C包装器来使我的c++可访问?(这是唯一的方法,我可以得到一个简单的测试用例在Windows与Visual Studio工作)。

对于我的情况,我的源代码已经在c++中,而不是C,在上面两个选项之间选择的考虑因素是什么?

FFI与动态C库一起工作。这意味着您必须向外部公开动态库。在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-things可用。

下面是你如何在javascript中包装它,当你编译了你的c++库为libmylibrary.dll/.so:

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

你可以做很多更酷的事情。点击这里查看

如果这是一个节点库,只需将您的方法放在module.exports中。下面是对上述c++代码进行包装的完整示例,使用同步的&异步方法:

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,但是它看起来很酷,可以为您生成这类包装器。

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

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

至于"是不是更好?"我想大多数事情都是这样。如果您使您的方法在C语言之外,它们将在几乎所有其他语言中工作,其中一些语言也具有FFI,因此您将在任何目标语言中编写上面的简单等效程序。这意味着需要维护的代码很少,除了基本的"加载c++库"answers"修改它的签名以使其适合X语言"。它不是特定于某个节点的。另一个好处是公共共享库(如教程示例中给出的sqlite)。您可能并不关心它们的确切版本,或者想用更多的c++代码来包装它,这些代码需要编译才能使用它。使用FFI,您可以用javascript包装预编译/安装的库。