У меня есть некоторый существующий код C ++, который выполняет числовую обработку в отдельном приложении C ++. Теперь я хочу использовать этот код в новом приложении node.js.
Изучая, как получить доступ к коду C ++ из node.js, мы подходим к двум вариантам:
node-ffi кажется хорошим вариантом для доступа к существующим библиотеки, но правильно ли я думаю, что если я использую node-ffi, мне придется написать оболочку C, чтобы сделать мой C ++ доступным? (Это был единственный способ заставить простой тестовый пример работать в Windows с Visual Studio).
Для моего случая, когда мой исходный код уже на C ++, а не на C, каковы соображения при выборе между двумя вариантами выше?
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 ++ доступной для C-вещи, как метод динамической библиотеки.
Вот как вы можете обернуть это в javascript после того, как вы скомпилировали свою C ++ lib как 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
};
Я не использовал Узел-FFI генерировать, но это выглядит довольно круто для создания таких оберток для вас.
Если бы я сохранил этот файл как mylibrary.js, я мог бы использовать его так:
var mylib = require('./mylibrary.js');
var num = mylib.fooSync(1);
// or
mylib.foo(1, function(er, num){
});
Что касается вопроса «это лучше?» Я так думаю, для большинства вещей. Если вы сделаете свои методы extern C, они будут работать практически на любом другом языке, некоторые из которых также имеют FFI, поэтому вы должны написать простой эквивалент вышеупомянутого на любом языке, на котором вы говорите. Это означает, что нужно поддерживать очень мало кода, кроме базовой «загрузки C ++ lib» и «возиться с его подписью, чтобы чувствовать себя подходящим для языка X». Это не специфично для узла. Еще один бонус — для общих разделяемых библиотек (например, sqlite, приведенный в учебном примере.) Возможно, вам все равно, какая у них версия, или хотите обернуть ее большим количеством кода C ++, который необходимо скомпилировать для ее использования. Используя FFI, вы можете обернуть предварительно скомпилированную / установленную библиотеку просто javascript.
Других решений пока нет …