Comment puis-je utiliser une bibliothèque C ++ à partir de node.js?

Réponses:

66

Regardez node-ffi .

node-ffi est un addon Node.js pour charger et appeler des bibliothèques dynamiques en utilisant du JavaScript pur. Il peut être utilisé pour créer des liaisons vers des bibliothèques natives sans écrire de code C ++.

Vadim Baryshev
la source
5
Différents compilateurs C ++ créent différents ABI, donc pour utiliser node-ffi, vous devrez peut-être envelopper votre code C ++ avec une interface C - ou du moins je l'ai fait pour que cela fonctionne sur Windows avec Visual Studio. Voir stackoverflow.com/questions/2045774/… pour plus de détails sur la façon de procéder. Ou devrais-je pouvoir utiliser node-ffi sur C ++ sans wrapper?
crêpe
1
Je sais que cela fait plus d'un an depuis ce commentaire mais ... est-il possible d'utiliser des bibliothèques C ++ sans wrapper C?
Miki de Arcayne
J'ai rencontré des problèmes de compilation VS 2017/2019 avec node-ffi. C'est un PITA majeur! Dépend-il de Python 2.7 ou s'agit-il simplement du processus de construction? Il doit y avoir un mécanisme LoadLibrary dans NodeJS pour une DLL Win32 standard?
tgraupmann
78

Il y a maintenant une nouvelle réponse à cette question. SWIG , à partir de la version 3.0, semble fournir des générateurs d'interface javascript pour Node.js, Webkit et v8.

J'utilise beaucoup SWIG pour Java et Python depuis un certain temps, et une fois que vous comprenez comment fonctionne SWIG, il n'y a presque aucun effort (par rapport à ffi ou l'équivalent dans le langage cible) nécessaire pour interfacer le code C ++ avec les langages SWIG les soutiens.

À titre d'exemple, disons que vous avez une bibliothèque avec l'en-tête 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;
        }
};

Pour utiliser cette classe dans node, vous écrivez simplement le fichier d'interface SWIG suivant (mylib.i):

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

Créez le fichier de liaison binding.gyp:

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

Exécutez les commandes suivantes:

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

Maintenant, en exécutant le nœud à partir du même dossier, vous pouvez faire:

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

Même si nous devions écrire 2 fichiers d'interface pour un si petit exemple, notez que nous n'avons pas eu à mentionner le MyClassconstructeur ni la sayHellométhode n'importe où, SWIG découvre ces choses et génère automatiquement des interfaces naturelles.

énobayram
la source
2
Après avoir joué un peu avec swig / node.js, il semble que swig ne puisse pas gérer les fonctions C ++ qui renvoient des tableaux (plus précisément: des fonctions qui renvoient des pointeurs vers des tableaux). Autrement dit, il semble que vous ne pouvez pas créer une fonction en C ++ qui renvoie quelque chose comme un tableau JavaScript et que swig la convertisse automatiquement pour vous.
George
5
@George SWIG est en effet un outil incroyable, mais ce n'est pas magique, et ce n'est pas une IA générale qui peut comprendre la sémantique de votre code C ++ et générer une interface respective. Veuillez faire attention à la façon dont la sémantique, les concepts de propriété et la gestion de la durée de vie de C ++ et de JavaScript sont fondamentalement différents.
enobayram
3
Vous pouvez donc afficher SWIG de deux manières: c'est un outil qui peut faire ce qu'il peut faire hors de la boîte et jouer selon ses règles. Cela signifie que vous ne devriez pas vous attendre à voir des tableaux javascript sortir des fonctions C ++ qui renvoient des tableaux. Ce que vous pouvez faire à la place, c'est envelopper votre fonction en C ++ afin qu'elle renvoie un objet qui se comporte comme un tableau ( std::vector<>par exemple, juste %include "std_vector.i"), et vous serez en mesure de le manipuler côté javascript d'une manière quelque peu maladroite. Notez que cette approche est toujours beaucoup plus facile et plus sûre que d'écrire vous-même FFI.
enobayram
3
L'autre façon dont vous pouvez utiliser SWIG est de comprendre la machine en dessous. Passez quelques mois à l'utiliser, découvrez ses fonctionnalités en profondeur. Ensuite, vous pouvez le faire générer l'interface que VOUS souhaitez. Vous voulez qu'il renvoie un tableau javascript pour un tableau C ++, très bien, vous pouvez le faire, mais vous devez d'abord apprendre à exprimer la sémantique exacte que vous attendez dans une telle interface et vous assurer qu'elle correspond bien à votre domaine problématique.
enobayram
3
Quoi qu'il en soit, je vous recommande de commencer par la première approche et d'affiner votre utilisation de SWIG en cours de route. C'est assez inspirant d'étudier ce que SWIG fait à votre code et comment vous pouvez le manipuler.
enobayram
11

Vous pouvez utiliser emscripten pour compiler du code C ++ en js.

N3UR0CHR0M
la source
16
Ce serait une mauvaise idée si l'objectif de l'OP est d'obtenir les avantages en termes de performances du C ++ compilé, et d'être pédant, cela ne répond pas à la question.
Greg
7
@Greg mais c'est quand même une idée à considérer. Les gens viennent sur cette page pour différents types de projets en cours. Je pense qu'Emscripten est une bonne option lorsque vous avez la base de code C / C ++ et que vous voulez simplement l'utiliser dans Nodejs.
AlexStack
1
- si l'objectif de l'OP est d'obtenir les avantages en termes de performances du C ++ compilé - Certains des avantages se traduisent avec emscripten, en particulier avec WASM: pas de surcharge GC, moins d'analyse et de surcharge JIT, entiers natifs, optimisations AOT.
ArtemGr
2

Il existe de nouvelles façons de connecter Node.js et C ++. S'il vous plaît, pillez Nan .

EDIT Le moyen le plus rapide et le plus simple est nbind . Si vous souhaitez écrire un add-on asynchrone, vous pouvez combiner la Asyncworkerclasse de nan.

Jasurbek Nabijonov
la source
1

Voici un article intéressant sur la mise en place de votre C ++ sur le Web avec Node.js

trois façons générales d'intégrer du code C ++ avec une application Node.js - bien qu'il existe de nombreuses variantes dans chaque catégorie:

  1. Automatisation - appelez votre C ++ en tant qu'application autonome dans un processus enfant.
  2. Bibliothèque partagée - regroupez vos routines C ++ dans une bibliothèque partagée (dll) et appelez ces routines directement depuis Node.js.
  3. Addon Node.js - compilez votre code C ++ en tant que module / addon Node.js natif.
sreepurna
la source
0

Faites attention à swig et C ++: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

L'exécution de SWIG sur des fichiers source C ++ (ce qui apparaîtrait dans un fichier .C ou .cxx) n'est pas recommandée. Même si SWIG peut analyser les déclarations de classe C ++, il ignore les déclarations qui sont découplées de leur définition de classe d'origine (les déclarations sont analysées, mais de nombreux messages d'avertissement peuvent être générés). Par exemple:

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

Il est rare qu'une classe C ++ soit limitée à un seul fichier .h.

De plus, les versions de swig prenant en charge JavaScript sont swig-3.0.1 ou version ultérieure.

Anton
la source
Je ne comprends pas ce que SWIG ferait avec la définition de de foo::bartoute façon. La définition d'un membre de classe concerne la mise en œuvre; les wrappers générés par SWIG concernent uniquement l'interface.
enobayram le