Jak mogę używać biblioteki C ++ z node.js?

Odpowiedzi:

66

Spójrz na node-ffi .

node-ffi to dodatek Node.js do ładowania i wywoływania bibliotek dynamicznych przy użyciu czystego JavaScript. Może być używany do tworzenia powiązań z natywnymi bibliotekami bez pisania kodu w C ++.

Vadim Baryshev
źródło
5
Różne kompilatory C ++ tworzą różne ABI, więc aby użyć node-ffi, być może będziesz musiał opakować swój kod C ++ interfejsem C - lub przynajmniej zrobiłem, aby to działało w systemie Windows z Visual Studio. Zobacz stackoverflow.com/questions/2045774/…, aby uzyskać szczegółowe informacje, jak to zrobić. A może powinienem móc używać node-ffi w C ++ bez opakowania?
naleśnik
1
Wiem, że minął ponad rok od czasu tego komentarza, ale ... czy można używać bibliotek C ++ bez opakowania C?
Miki de Arcayne,
Napotkałem problemy z kompilacją VS 2017/2019 z node-ffi. To poważna PITA! Czy jest to zależne od Pythona 2.7, czy to tylko proces kompilacji? W NodeJS musi istnieć mechanizm LoadLibrary dla standardowej biblioteki DLL Win32?
tgraupmann
79

Teraz jest nowa odpowiedź na to pytanie. Wydaje się, że od wersji 3.0 SWIG zapewnia generatory interfejsów javascript dla Node.js, Webkit i v8.

Od jakiegoś czasu intensywnie używam SWIG dla Javy i Pythona, a kiedy już zrozumiesz, jak działa SWIG, prawie nie ma wysiłku (w porównaniu z ffi lub odpowiednikiem w języku docelowym) potrzebnym do połączenia kodu C ++ z językami, które SWIG obsługuje.

Jako mały przykład załóżmy, że masz bibliotekę z nagłówkiem 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;
        }
};

Aby użyć tej klasy w węźle, wystarczy napisać następujący plik interfejsu SWIG (mylib.i):

%module "mylib"
%{
#include "myclass.h"
%}
%include "myclass.h"

Utwórz plik wiązania binding.gyp:

{
  "targets": [
    {
      "target_name": "mylib",
      "sources": [ "mylib_wrap.cxx" ]
    }
  ]
}

Uruchom następujące polecenia:

swig -c++ -javascript -node mylib.i
node-gyp build

Teraz, uruchamiając węzeł z tego samego folderu, możesz wykonać:

> var mylib = require("./build/Release/mylib")
> var c = new mylib.MyClass(5)
> c.sayHello()
Hello, my number is:5

Chociaż musieliśmy napisać 2 pliki interfejsów dla tak małego przykładu, zauważ, że nie musieliśmy nigdzie wspominać o MyClasskonstruktorze ani o sayHellometodzie, SWIG odkrywa te rzeczy i automatycznie generuje naturalne interfejsy.

enobayram
źródło
2
Po dłuższej zabawie z swig / node.js okazuje się, że swig nie obsługuje funkcji C ++, które zwracają tablice (a dokładniej: funkcje, które zwracają wskaźniki do tablic). Oznacza to, że wygląda na to, że nie możesz zbudować funkcji w C ++, która zwraca coś w rodzaju tablicy JavaScript i ma swig automatycznie ją konwertować.
George
5
@George SWIG jest rzeczywiście niesamowitym narzędziem, ale to nie jest magia i nie jest to jakaś ogólna sztuczna inteligencja, która może zrozumieć semantykę twojego kodu C ++ i wygenerować odpowiedni interfejs. Zwróć uwagę na to, jak semantyka C ++ i javascript, koncepcje własności i zarządzanie cyklem życia są zasadniczo różne.
enobayram
3
Możesz więc patrzeć na SWIG na dwa sposoby: Jest to narzędzie, które może zrobić to, co potrafi, po wyjęciu z pudełka i grać według jego zasad. Oznacza to, że nie powinieneś oczekiwać, że tablice javascript wyskakują z funkcji C ++, które zwracają tablice. Zamiast tego możesz owinąć swoją funkcję w C ++ tak, aby zwracała obiekt, który zachowuje się jak tablica ( std::vector<>na przykład po prostu %include "std_vector.i"), i będziesz mógł manipulować nią po stronie javascript w nieco niezręczny sposób. Zauważ, że to podejście jest nadal o wiele łatwiejsze i bezpieczniejsze niż samodzielne pisanie FFI.
enobayram
3
Innym sposobem wykorzystania SWIG jest zrozumienie maszyn znajdujących się pod spodem. Poświęć kilka miesięcy na korzystanie z niego, dokładnie poznaj jego funkcje. Następnie możesz sprawić, by wygenerował interfejs, którego chcesz. Chcesz, aby zwracał tablicę javascript dla tablicy C ++, w porządku, możesz to zrobić, ale najpierw powinieneś nauczyć się, jak dokładnie wyrazić semantykę, której oczekujesz w takim interfejsie i upewnić się, że dobrze odwzorowuje domenę, w której występuje problem.
enobayram
3
Tak czy inaczej, polecam zacząć od pierwszego podejścia i po drodze udoskonalić wykorzystanie SWIG-a. Inspirujące jest zbadanie, co SWIG robi z twoim kodem i jak możesz nim manipulować.
enobayram
11

Możesz użyć emscripten do skompilowania kodu C ++ do js.

N3UR0CHR0M
źródło
16
Byłby to zły pomysł, jeśli celem OP jest uzyskanie wydajności skompilowanego C ++, a mówiąc pedantycznie, nie odpowiada na pytanie.
Greg
7
@Greg, ale nadal jest to pomysł wart rozważenia. Ludzie przychodzą na tę stronę po różne rodzaje projektów. Myślę, że Emscripten jest dobrą opcją, gdy masz bazę kodu C / C ++ i po prostu chcesz jej użyć w Nodejs.
AlexStack
1
- jeśli celem OP jest uzyskanie korzyści związanych z wydajnością skompilowanego C ++ - Niektóre korzyści przekładają się na emscripten, szczególnie w przypadku WASM: brak narzutu GC, mniej narzutu na parsowanie i JIT, natywne liczby całkowite, optymalizacje AOT.
ArtemGr,
2

Istnieją nowsze sposoby łączenia Node.js i C ++. Proszę, okradnij Nan .

EDYCJA Najszybszym i najłatwiejszym sposobem jest nbind . Jeśli chcesz napisać dodatek asynchroniczny, możesz połączyć Asyncworkerklasy z nan.

Jasurbek Nabijonov
źródło
1

Oto interesujący artykuł na temat pobierania C ++ do sieci przy użyciu Node.js.

trzy ogólne sposoby integracji kodu C ++ z aplikacją Node.js - chociaż istnieje wiele odmian w ramach każdej kategorii:

  1. Automatyzacja - wywołaj C ++ jako samodzielną aplikację w procesie potomnym.
  2. Biblioteka współdzielona - spakuj procedury C ++ do biblioteki współdzielonej (dll) i wywołaj te procedury bezpośrednio z Node.js.
  3. Node.js Addon - skompiluj swój kod C ++ jako natywny moduł / dodatek Node.js.
sreepurna
źródło
0

Uważaj na swig i C ++: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

Uruchamianie SWIG na plikach źródłowych C ++ (które pojawiłyby się w pliku .C lub .cxx) nie jest zalecane. Chociaż SWIG może analizować deklaracje klas C ++, ignoruje deklaracje, które są oddzielone od ich oryginalnej definicji klasy (deklaracje są analizowane, ale może zostać wygenerowanych wiele komunikatów ostrzegawczych). Na przykład:

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

Rzadko kiedy klasa C ++ jest ograniczona tylko do jednego pliku .h.

Ponadto wersja swig obsługująca JavaScript to swig-3.0.1 lub nowsza.

Anton
źródło
I tak nie rozumiem, co SWIG zrobiłby z definicją foo::bar. Definicja członka klasy dotyczy implementacji; otoki generowane przez SWIG dotyczą interfejsu.
enobayram
0

Wypróbuj shelljs, aby wywołać program c / c ++ lub biblioteki współdzielone za pomocą programu węzłowego z linux / unix. node-cmd opcja w systemie Windows. Oba pakiety w zasadzie pozwalają nam wywołać program c / c ++ podobnie do sposobu, w jaki wywołujemy z terminala / wiersza poleceń.

Np. W ubuntu:

const shell = require('shelljs');

shell.exec("command or script name");

W oknach:

const cmd = require('node-cmd');
cmd.run('command here');

Uwaga: shelljs i node-cmd służą do uruchamiania poleceń systemu operacyjnego, a nie specyficznych dla c / c ++.

Som
źródło