Wie kann ich eine C ++ - Bibliothek aus node.js verwenden?

Antworten:

66

Schauen Sie sich node-ffi an .

node-ffi ist ein Node.js-Addon zum Laden und Aufrufen dynamischer Bibliotheken mit reinem JavaScript. Es kann verwendet werden, um Bindungen an native Bibliotheken zu erstellen, ohne C ++ - Code zu schreiben.

Vadim Baryshev
quelle
5
Verschiedene C ++ - Compiler erstellen unterschiedliche ABIs. Um Node-ffi zu verwenden, müssen Sie Ihren C ++ - Code möglicherweise mit einer C-Schnittstelle umschließen - oder zumindest, damit dies unter Windows mit Visual Studio funktioniert. Weitere Informationen hierzu finden Sie unter stackoverflow.com/questions/2045774/… . Oder sollte ich Node-ffi unter C ++ ohne Wrapper verwenden können?
Pfannkuchen
1
Ich weiß, seit diesen Kommentaren ist mehr als ein Jahr vergangen, aber ... ist es möglich, C ++ - Bibliotheken ohne C-Wrapper zu verwenden?
Miki de Arcayne
Ich bin auf VS 2017/2019 Kompilierungsprobleme mit Node-ffi gestoßen. Es ist eine große PITA! Ist es abhängig von Python 2.7 oder ist das nur der Build-Prozess? In NodeJS muss ein LoadLibrary-Mechanismus für eine Standard-Win32-DLL vorhanden sein.
Tgraupmann
78

Auf diese Frage gibt es jetzt eine neue Antwort. SWIG scheint ab Version 3.0 Javascript-Schnittstellengeneratoren für Node.js, Webkit und v8 bereitzustellen.

Ich habe SWIG für eine Weile ausgiebig für Java und Python verwendet, und wenn Sie erst einmal verstanden haben, wie SWIG funktioniert, sind fast keine Anstrengungen (im Vergleich zu ffi oder dem Äquivalent in der Zielsprache) erforderlich, um C ++ - Code mit den Sprachen von SWIG zu verbinden unterstützt.

Angenommen, Sie haben eine Bibliothek mit dem Header 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;
        }
};

Um diese Klasse im Knoten zu verwenden, schreiben Sie einfach die folgende SWIG-Schnittstellendatei (mylib.i):

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

Erstellen Sie die Bindungsdatei binding.gyp:

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

Führen Sie die folgenden Befehle aus:

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

Wenn Sie nun den Knoten aus demselben Ordner ausführen, können Sie Folgendes tun:

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

Obwohl wir für ein so kleines Beispiel zwei Schnittstellendateien schreiben mussten, beachten Sie, dass wir weder den MyClassKonstruktor noch die sayHelloMethode irgendwo erwähnen mussten. SWIG entdeckt diese Dinge und generiert automatisch natürliche Schnittstellen.

Enobayram
quelle
2
Nach einigem Spielen mit swig / node.js scheint es, dass swig keine C ++ - Funktionen verarbeiten kann, die Arrays zurückgeben (genauer: Funktionen, die Zeiger auf Arrays zurückgeben). Das heißt, es scheint, dass Sie in C ++ keine Funktion erstellen können, die so etwas wie ein JavaScript-Array zurückgibt und von swig automatisch für Sie konvertiert wird.
George
5
@ George SWIG ist in der Tat ein erstaunliches Werkzeug, aber es ist keine Magie, und es ist keine allgemeine KI, die die Semantik Ihres C ++ - Codes verstehen und eine entsprechende Schnittstelle generieren kann. Bitte achten Sie darauf, wie sich die Semantik, die Besitzkonzepte und das Lifetime Management von C ++ und Javascript grundlegend unterscheiden.
Enobayram
3
Sie können SWIG also auf zwei Arten anzeigen: Es ist ein Tool, das das kann, was es sofort kann, und nach seinen Regeln spielt. Das heißt, Sie sollten nicht erwarten, dass Javascript-Arrays aus C ++ - Funktionen herausspringen, die Arrays zurückgeben. Stattdessen können Sie Ihre Funktion in C ++ umbrechen, sodass sie ein Objekt zurückgibt, das sich wie ein Array verhält ( std::vector<>z. B. nur %include "std_vector.i"), und Sie können es auf der Javascript-Seite auf etwas umständliche Weise bearbeiten. Beachten Sie, dass dieser Ansatz immer noch viel einfacher und sicherer ist als das Schreiben von FFI selbst.
Enobayram
3
Die andere Möglichkeit, SWIG zu verwenden, besteht darin, die darunter liegenden Maschinen zu verstehen. Verbringen Sie ein paar Monate damit und lernen Sie die Funktionen ausführlich kennen. Dann können Sie die gewünschte Schnittstelle generieren lassen. Sie möchten, dass es ein Javascript-Array für ein C ++ - Array zurückgibt. Gut, Sie können es tun, aber Sie sollten zuerst lernen, wie Sie die genaue Semantik ausdrücken, die Sie in einer solchen Schnittstelle erwarten, und sicherstellen, dass sie gut zu Ihrer Problemdomäne passt.
Enobayram
3
In jedem Fall empfehle ich Ihnen, mit dem ersten Ansatz zu beginnen und die Verwendung von SWIG unterwegs zu verfeinern. Es ist sehr inspirierend zu untersuchen, was SWIG mit Ihrem Code macht und wie Sie ihn manipulieren können.
Enobayram
11

Sie können emscripten verwenden , um C ++ - Code in js zu kompilieren.

N3UR0CHR0M
quelle
16
Dies wäre eine schlechte Idee, wenn das Ziel des OP darin besteht, die Leistungsvorteile von kompiliertem C ++ zu nutzen, und pedantisch zu sein, beantwortet es die Frage nicht.
Greg
7
@ Greg, aber es ist immer noch eine Idee, die es wert ist, in Betracht gezogen zu werden. Leute kommen auf diese Seite für verschiedene Arten von Projekten in der Hand. Ich denke, Emscripten ist eine gute Option, wenn Sie die C / C ++ - Codebasis haben und sie nur in Nodejs verwenden möchten.
AlexStack
1
- Wenn das Ziel des OP darin besteht, die Leistungsvorteile von kompiliertem C ++ zu nutzen - Einige der Vorteile lassen sich mit emscripten übersetzen, insbesondere mit WASM: kein GC-Overhead, weniger Parsing- und JIT-Overhead, native Ganzzahlen, AOT-Optimierungen.
ArtemGr
2

Es gibt neuere Möglichkeiten, Node.js und C ++ zu verbinden. Bitte plündere Nan .

BEARBEITEN Der schnellste und einfachste Weg ist nbind . Wenn Sie ein asynchrones Add-On schreiben möchten, können Sie eine AsyncworkerKlasse aus nan kombinieren .

Jasurbek Nabijonov
quelle
1

Hier ist ein interessanter Artikel darüber, wie Sie Ihr C ++ mit Node.js ins Web bringen können

Drei allgemeine Möglichkeiten zur Integration von C ++ - Code in eine Node.js-Anwendung - obwohl es in jeder Kategorie viele Variationen gibt:

  1. Automatisierung - Rufen Sie Ihr C ++ als eigenständige App in einem untergeordneten Prozess auf.
  2. Gemeinsame Bibliothek - Packen Sie Ihre C ++ - Routinen in eine gemeinsam genutzte Bibliothek (DLL) und rufen Sie diese Routinen direkt von Node.js aus auf.
  3. Node.js Addon - Kompilieren Sie Ihren C ++ - Code als natives Node.js-Modul / Addon.
Sreepurna
quelle
0

Seien Sie vorsichtig mit swig und C ++: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

Das Ausführen von SWIG in C ++ - Quelldateien (was in einer C- oder CXX-Datei angezeigt wird) wird nicht empfohlen. Obwohl SWIG C ++ - Klassendeklarationen analysieren kann, werden Deklarationen ignoriert, die von ihrer ursprünglichen Klassendefinition entkoppelt sind (die Deklarationen werden analysiert, es können jedoch viele Warnmeldungen generiert werden). Beispielsweise:

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

Es ist selten, dass eine C ++ - Klasse auf nur eine .h-Datei beschränkt ist.

Die Versionen von swig, die JavaScript unterstützen, sind swig-3.0.1 oder höher.

Anton
quelle
Ich verstehe nicht, was SWIG mit der Definition von foo::barsowieso machen würde. Bei der Definition eines Klassenmitglieds dreht sich alles um die Implementierung. Bei den von SWIG generierten Wrappern dreht sich alles um die Schnittstelle.
Enobayram