Как я могу использовать библиотеку C ++ из node.js?

Ответы:

66

Посмотрите на node -ffi .

node-ffi - это надстройка Node.js для загрузки и вызова динамических библиотек с использованием чистого JavaScript. Его можно использовать для создания привязок к собственным библиотекам без написания кода C ++.

Вадим Барышев
источник
5
Различные компиляторы C ++ создают разные ABI, поэтому для использования node-ffi вам, возможно, придется обернуть свой код C ++ интерфейсом C - или, по крайней мере, я сделал, чтобы это работало в Windows с помощью Visual Studio. См. Stackoverflow.com/questions/2045774/…, чтобы узнать, как это сделать. Или я могу использовать node-ffi на C ++ без оболочки?
блин
1
Я знаю, что с момента этого комментария прошло больше года, но ... можно ли использовать библиотеки C ++ без оболочки C?
Мики де Аркейн
Я столкнулся с проблемами компиляции VS 2017/2019 с node-ffi. Это крупная ПИТА! Это зависит от Python 2.7 или это всего лишь процесс сборки? В NodeJS должен быть механизм LoadLibrary для стандартной Win32 DLL?
tgraupmann
78

На этот вопрос есть свежий ответ. SWIG , начиная с версии 3.0, похоже, предоставляет генераторы интерфейса javascript для Node.js, Webkit и v8.

Некоторое время я широко использую SWIG для Java и Python, и как только вы поймете, как работает 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 файла интерфейса для такого небольшого примера, обратите внимание, что нам не нужно было нигде упоминать MyClassконструктор или sayHelloметод, SWIG обнаруживает эти вещи и автоматически генерирует естественные интерфейсы.

enobayram
источник
2
Поиграв немного с swig / node.js, выяснилось, что swig не может обрабатывать функции C ++, возвращающие массивы (точнее: функции, возвращающие указатели на массивы). То есть, похоже, вы не можете создать функцию на C ++, которая возвращает что-то вроде массива JavaScript, и swig автоматически конвертирует его для вас.
Джордж
5
@George SWIG - действительно потрясающий инструмент, но это не волшебство и не какой-то общий ИИ, который может понять семантику вашего кода C ++ и сгенерировать соответствующий интерфейс. Обратите внимание на то, как семантика C ++ и javascript, концепции владения и управление временем жизни фундаментально различаются.
энобайрам
3
Таким образом, вы можете рассматривать SWIG двумя способами: это инструмент, который может делать то, что он умеет, из коробки, и играть по своим правилам. Это означает, что вы не должны ожидать появления массивов javascript из функций C ++, возвращающих массивы. Вместо этого вы можете обернуть свою функцию в C ++ так, чтобы она возвращала объект, который ведет себя как массив ( std::vector<>например, просто %include "std_vector.i"), и вы сможете манипулировать им на стороне javascript несколько неудобным образом. Обратите внимание, что этот подход по-прежнему проще и безопаснее, чем писать FFI самостоятельно.
энобайрам
3
Другой способ использовать SWIG - это понять механизмы, лежащие в основе. Потратьте несколько месяцев на его использование, подробно изучите его возможности. Затем вы можете заставить его генерировать нужный вам интерфейс. Вы хотите, чтобы он возвращал массив javascript для массива C ++, хорошо, вы можете это сделать, но сначала вы должны узнать, как выразить точную семантику, которую вы ожидаете в таком интерфейсе, и убедиться, что он хорошо соответствует вашей проблемной области.
enobayram
3
В любом случае, я рекомендую вам начать с первого подхода и попутно усовершенствовать использование SWIG. Очень вдохновляет изучать, что SWIG делает с вашим кодом и как вы можете им манипулировать.
enobayram
11

Вы можете использовать emscripten для компиляции кода C ++ в js.

N3UR0CHR0M
источник
16
Это было бы плохой идеей, если цель OP - получить преимущества производительности от скомпилированного C ++, и, если быть педантичным, он не отвечает на вопрос.
Грег
7
@Greg, но все же это стоит задуматься. Люди заходят на эту страницу для реализации различных проектов. Я думаю, что Emscripten - хороший вариант, когда у вас есть база кода C / C ++ и вы просто хотите использовать ее в Nodejs.
AlexStack
1
- если цель OP - получить преимущества производительности скомпилированного C ++ - Некоторые из преимуществ транслируются с помощью emscripten, особенно с WASM: отсутствие накладных расходов на сборщик мусора, меньшие затраты на синтаксический анализ и JIT, собственные целые числа, оптимизация AOT.
ArtemGr 08
2

Появились более новые способы соединения Node.js и C ++. Пожалуйста, обыщите Нан .

РЕДАКТИРОВАТЬ Самый быстрый и простой способ - это nbind . Если вы хотите написать асинхронное дополнение, вы можете комбинировать Asyncworkerкласс из nan.

Жасурбек Набижонов
источник
1

Вот интересная статья о том, как перенести ваш C ++ в Интернет с помощью Node.js

три основных способа интеграции кода C ++ с приложением Node.js - хотя в каждой категории есть множество вариантов:

  1. Автоматизация - вызовите свой C ++ как отдельное приложение в дочернем процессе.
  2. Общая библиотека - упакуйте свои подпрограммы C ++ в общую библиотеку (dll) и вызывайте эти подпрограммы напрямую из Node.js.
  3. Node.js Addon - скомпилируйте свой код C ++ как собственный модуль / надстройку Node.js.
sreepurna
источник
0

Остерегайтесь swig и C ++: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

Запускать SWIG в исходных файлах C ++ (которые появляются в файлах .C или .cxx) не рекомендуется. Несмотря на то, что SWIG может анализировать объявления классов C ++, он игнорирует объявления, которые отделены от их исходного определения класса (объявления анализируются, но может генерироваться множество предупреждающих сообщений). Например:

/* Not supported by SWIG */
int foo::bar(int) {
    ... whatever ...
}

Редко бывает, чтобы класс C ++ был ограничен только одним файлом .h.

Кроме того, версия swig, поддерживающая JavaScript, - это swig-3.0.1 или новее.

Антон
источник
Я все равно не понимаю, что СВИГ сделал бы с определением foo::bar. Определение члена класса связано с реализацией; все обертки, которые генерирует SWIG, связаны с интерфейсом.
энобайрам