Расширение node -ffi vs. node для доступа к существующим функциям С++

У меня есть код С++, который выполняет численную обработку в автономном приложении С++. Теперь я хочу использовать этот код в новом приложении node.js.

Исследование того, как получить доступ к С++-коду из node.js, появляется два параметра:

  • Напишите расширение node.js
  • Используйте node-ffi

node -ffi кажется хорошим вариантом для доступа к существующим библиотекам, но я правильно думаю, если я использую node -ffi Мне нужно написать C-оболочку, чтобы сделать мой С++ доступным? (Это был единственный способ получить простой тестовый пример для работы с Windows с Visual Studio).

В моем случае, когда мой исходный код уже находится на С++, а не C, каковы соображения при выборе между двумя указанными выше параметрами?

Ответы

Ответ 1

FFI работает с динамическими библиотеками 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-вещей, как метод динамической библиотеки.

Вот как вы обертываете это в javascript, после того как вы скомпилировали свой С++ lib как libmylibrary.dll/.so:

var ffi = require('ffi');

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

Есть много более прохладных вещей, которые вы можете сделать. Проверьте это, здесь

Если это библиотека node, просто поместите свои методы в module.exports. Вот полный пример переноса вышеуказанного кода на С++ с синхронными и асинхронными методами:

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){

});

Что касается вопроса "лучше ли?" Я так думаю, для большинства вещей. Если вы сделаете свои методы extern C, они будут работать практически на любом другом языке, некоторые из которых также имеют FFI, поэтому вы должны написать простой эквивалент выше, независимо от вашего целевого языка. Это означает, что очень мало кода для поддержки, кроме базового "load С++ lib" и "беспорядок с его подписи, чтобы чувствовать себя правильно для языка X". Это не относится к node. Еще один бонус - для общих разделяемых библиотек (например, sqlite, приведенных в учебном примере.) Возможно, вам все равно, какая версия у них есть, или хотите обернуть его большим количеством кода на С++, который необходимо скомпилировать для его использования. Используя FFI, вы можете обернуть предварительно скомпилированную/установленную библиотеку только с помощью javascript.