138

How can I use a C++ library from node.js?

Software Engineer
  • 15,457
  • 7
  • 74
  • 102
MaiaVictor
  • 51,090
  • 44
  • 144
  • 286
  • 10
    The key word is `extension`. Google [c++ nodejs extension](https://www.google.co.uk/search?q=c%2B%2B+nodejs+extension) – Peter Wood Mar 09 '12 at 07:44
  • 5
    Follow this link. It has provided a sample program and explained it step by step. http://www.benfarrell.com/2013/01/03/c-and-node-js-an-unholy-combination-but-oh-so-right/ –  Jul 02 '13 at 07:56

7 Answers7

83

There is a fresh answer to that question now. SWIG, as of version 3.0 seems to provide javascript interface generators for Node.js, Webkit and v8.

I've been using SWIG extensively for Java and Python for a while, and once you understand how SWIG works, there is almost no effort(compared to ffi or the equivalent in the target language) needed for interfacing C++ code to the languages that SWIG supports.

As a small example, say you have a library with the 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;
        }
};

In order to use this class in node, you simply write the following SWIG interface file (mylib.i):

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

Create the binding file binding.gyp:

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

Run the following commands:

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

Now, running node from the same folder, you can do:

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

Even though we needed to write 2 interface files for such a small example, note how we didn't have to mention the MyClass constructor nor the sayHello method anywhere, SWIG discovers these things, and automatically generates natural interfaces.

enobayram
  • 4,650
  • 23
  • 36
  • This looks incredibly simple! Thanks for the worked example – Rik Smith-Unna Jan 18 '16 at 14:14
  • This answer introduced me to swig, which is amazing. It automates all of the addon boilerplate code! This is too good to be true. Is there some sort of massive performance trade-off at play here? – George Mar 26 '16 at 00:25
  • 2
    After playing with swig/node.js for a bit, it appears that swig cannot handle C++ functions that return arrays (more precisely: functions that return pointers to arrays). That is, it seems you cannot build a function in C++ that returns something like a JavaScript array and have swig automatically convert it for you. – George Mar 26 '16 at 03:12
  • 5
    @George SWIG is an amazing tool indeed, but it's not magic, and it's not some general AI that can understand the semantics of your C++ code and generate a respective interface. Please pay attention to how C++'s and javascript's semantics, ownership concepts and lifetime management are fundamentally different. – enobayram Mar 26 '16 at 06:55
  • 3
    So you can view SWIG in two ways: It's a tool that can do what it can do out of the box, and play by its rules. That means, you shouldn't expect to see javascript arrays pop out of C++ functions that return arrays. What you can instead do is to wrap your function in C++ so that it returns an object that behaves like an array (`std::vector<>` for instance, just `%include "std_vector.i"`), and you'll be able to manipulate it on the javascript side in a somewhat awkward way. Note that this approach is still way easier and safer than writing FFI yourself. – enobayram Mar 26 '16 at 06:58
  • 3
    The other way you can use SWIG, is to understand the machinery underneath. Spend a few months using it, learn its features in depth. Then you can make it generate the interface YOU want. You want it to returns a javascript array for a C++ array, fine, you can do it, but you should first learn how to express the exact semantics you expect in such an interface and make sure that it maps well to your problem domain. – enobayram Mar 26 '16 at 07:01
  • 3
    Either way, I recommend you to start with the first approach, and refine your use of SWIG on the way. It's quite inspiring to study what SWIG does to your code and how you can manipulate it. – enobayram Mar 26 '16 at 07:02
  • 1
    I created a git repo with your example: https://github.com/phaffonso/node-cpp-example - thanks, works beautifully – Pedro Affonso Nov 24 '16 at 11:26
68

Look at node-ffi.

node-ffi is a Node.js addon for loading and calling dynamic libraries using pure JavaScript. It can be used to create bindings to native libraries without writing any C++ code.

Vadim Baryshev
  • 25,689
  • 4
  • 56
  • 48
  • 5
    Different C++ compilers create different ABIs, so to use node-ffi you might have to wrap your C++ code with a C interface - or at least I did to get this working on Windows with Visual Studio. See http://stackoverflow.com/questions/2045774/developing-c-wrapper-api-for-object-oriented-c-code for details on how to do this. Or should I be able to use node-ffi on C++ without a wrapper? – pancake May 28 '13 at 02:12
  • 1
    I know it's more than a year since this comments but... is it possible to use C++ libs without a C wrapper? – Miki de Arcayne Sep 05 '13 at 11:37
  • I ran into VS 2017/2019 compile issues with node-ffi. It's a major PITA! Is it dependent on Python 2.7 or is that just the build process? There must be a LoadLibrary mechanism in NodeJS for a standard Win32 DLL? – tgraupmann Oct 30 '19 at 20:48
  • 1
    node-ffi is not supported anymore and not compiles seamlessly, not recommended. – Zvi vex Mar 04 '21 at 12:23
12

You could use emscripten to compile C++ code into js.

N3UR0CHR0M
  • 193
  • 1
  • 5
  • 17
    This would be a bad idea if the OP's goal is to get the performance benefits of compiled C++, and to be pedantic it doesn't answer the question. – Greg May 15 '14 at 02:16
  • 7
    @Greg but still it's a idea worth considering. People come to this page for various types of projects in hand. I think Emscripten is a good option when you have the C/C++ code base and just want to use it in Nodejs. – AlexStack Nov 19 '14 at 16:23
  • 1
    - *if the OP's goal is to get the performance benefits of compiled C++* - Some of the benefits translate with emscripten, particularly with WASM: no GC overhead, less parsing and JIT overhead, native integers, AOT optimizations. – ArtemGr Jul 08 '19 at 17:29
3

There newer ways to connect Node.js and C++. Please, loot at Nan.

EDIT The fastest and easiest way is nbind. If you want to write asynchronous add-on you can combine Asyncworker class from nan.

JHH
  • 8,567
  • 8
  • 47
  • 91
Jasurbek Nabijonov
  • 1,607
  • 3
  • 24
  • 37
2

Here is an interesting article on Getting your C++ to the Web with Node.js

three general ways of integrating C++ code with a Node.js application - although there are lots of variations within each category:

  1. Automation - call your C++ as a standalone app in a child process.
  2. Shared library - pack your C++ routines in a shared library (dll) and call those routines from Node.js directly.
  3. Node.js Addon - compile your C++ code as a native Node.js module/addon.
sreepurna
  • 1,562
  • 2
  • 17
  • 32
1

Try shelljs to call c/c++ program or shared libraries by using node program from linux/unix . node-cmd an option in windows. Both packages basically enable us to call c/c++ program similar to the way we call from terminal/command line.

Eg in ubuntu:

const shell = require('shelljs');

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

In windows:

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

Note: shelljs and node-cmd are for running os commands, not specific to c/c++.

Som
  • 1,467
  • 13
  • 11
0

Becareful with swig and C++: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

Running SWIG on C++ source files (what would appear in a .C or .cxx file) is not recommended. Even though SWIG can parse C++ class declarations, it ignores declarations that are decoupled from their original class definition (the declarations are parsed, but a lot of warning messages may be generated). For example:

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

It's rarely to have a C++ class limited to only one .h file.

Also, the versions of swig supporting JavaScript is swig-3.0.1 or later.

JHH
  • 8,567
  • 8
  • 47
  • 91
Anton
  • 41
  • 8
  • I don't understand what SWIG would do with the definition of `foo::bar` anyway. The definition of a class member is all about implementation; the wrappers that SWIG generate are all about the interface. – enobayram Jul 20 '17 at 17:05
  • Shouldn't this rather be a comment on the SWIG answer? – MAChitgarha Mar 23 '23 at 19:18