How to call a shared C library from NodeJS

In  my last post I showed you how to call C functions from NodeJS. Now, we want to package the C functions into a shared library and call that from NodeJS. To do that we will first need to create the shared library.

Creating shared libraries

We start with creating our object files. Note the -fpic flag which will create position independent code.

// create object files from .cc code
$ gcc -std=c++11 -c -fpic some_cpp_file.cc
// create object files from .c code
$ gcc -c -fpic some_cpp_file.c

Then link everything and create the shared library

$ gcc -shared -o libmytest.so some_cpp_file.o some_cpp_filw.o

You can also put that into a Makefile:

CC=     gcc
CFLAGS= -g -W -fpic
TARGET= libname.so
SRC=   some_cpp_file.cc some_c_file.c

$(TARGET): some_cpp_file.o some_c_file.o
 ${CC} -shared -o $@ $^

# Create position independent code:
%.o: %.cc
 $(CC) $(CFLAGS) -std=c++11 -c $<
%.o: %.c
 $(CC) $(CFLAGS) -c $<

Finally, to allow other programs to find your shared library you will have to update your $LD_LIBRARY_PATH with the path to the .so file. In my case it looks something like this:

$ export LD_LIBRARY_PATH=/home/debian/gsoc/preparation/interface/lib:$LD_LIBRARY_PATH

// check it
$ echo $LD_LIBRARY_PATH
/home/debian/gsoc/preparation/interface/lib:

Adding the library to bindings.gyp

In order to access the shared library from NodeJS we will use node-gyp again. Add the library to your bindings.gyp file, it should looks like that:

{
  "targets": [
    {
      "target_name": "your_module_name",
      "cflags": ["-Wall", "-std=c++11"],
      "sources": [ "path/to/cpp/file.cc" ],
      "include_dirs" : [
        "<!(node -e \"require('path/to/node_modules/nan')\")"
      ],
      "libraries": [ "-lmytest", "-L/home/debian/gsoc/preparation/interface/lib" ]
    }
  ]
}

Note that /home/debian/gsoc/preparation/interface/lib is the path to my .so file.

We can now rebuild our project with “node-gyp rebuild” and use the library from our C++ code. To do that, just include the header file (the one located in the library folder) like so:

extern "C" {
    #include "path/to/library/libname.h"
}

The “extern C” is only needed as our library is written in C and we are currently using C++. See my last post for more information. I uploaded my code to GitHub here: https://github.com/ordsen/gsoc-preparation/tree/master/nodejs_server_example/interface

Since I’m developing on Mac but the software should run on linux (BeagleBone) I created two subfolders gyp_mac and gyp_linux. I navigate to the appropriate folder to rebuild the node binding on both platforms, but as on OSX there are no .so files I just use the library directly.

Referencing the library methods from JS happens just like shown in my last post. Also checkout this blog if you do not want to write a wrapper but instead access the C library directly from JS with the Foreign Function Interface (ffi-API).

How to call a shared C library from NodeJS