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 ++.


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.


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.


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.


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.

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.


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 ++.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.