cwrap

Generate NodeJS bindings for modules that have a C interface

npm install cwrap
8 downloads in the last month

CWrap

CWrap is a NodeJS utility I've created to help me create (NodeJS) wrappers for library modules that have a C interface.

At its core, CWrap is little more than a template engine with a slight resemblance to Mustache. The rest of the work is more or less left to the programmer, though the module provides a function that extracts the interface description from an XML file generated by SWIG.

Prerequisites

  • Make sure you have installed and read about node-gyp, the awesome tool that makes it easy and straightforward to create native extensions for NodeJS.
  • If you haven't already, get acquainted with how to actually write NodeJS bindings. A good place to start is this slideshow; you may also have to have a look at the V8 Embedder's Guide.
  • Install SWIG, and put the executable in your path.

Overview

The process to create NodeJS bindings for your C module is easily summarized:

  • call SWIG on your header file to generate an XML description of the interface
  • use CWrap's parseSwigXML() function to extract a JSON interface description from the XML
  • apply a code template on the interface description to obtain the wrapper code

Getting started

Unfortunately, the sample provided at the time of writing cannot actually be used (it will fail at the linker stage), as it generates bindings for a module that is not free software (for lack of time, I just used what I had already done). However, the sample should still be sufficient to point you in the right direction.

It is probably best to start with the sample template nodebindings.tmpl.cc - perhaps glancing at the generated source lsdisplay2_wrap.cc from time to time will help you not to get lost in all those template markers.

Let's get the template syntax out of the way - it's really simple:

  • Tags are introduced with the characters {{$ and closed with }}.
  • The foreach (or its alias forall) tag will iterate over the elements of an array or object; the block it controls must be closed with a end tag.
  • The if, elsif, else and end tags will work together just as you'd expect them to. There is no need for parentheses after if or elsif; otherwise, the syntax is JavaScript, though array indices are not supported (yet?)
  • The = tag inserts a value into the code. It's an inline tag and does not need or support a closing end.
  • Tags starting with a dash - are considered comments. No closing tag.
  • The macro tag defines a named "subroutine"
  • The call tag executes a macro
  • The list tag (inline, no closing tag) is used to fill out the parameter list of a function call.

Next should come the generate.js code, which is the code you would actually run in order to obtain the wrapper code. What it does is read the XML generated by SWIG, extract from that the basic interface description, then run a custom function called postProcess() that sifts through the interface description and does things like converting functions to methods, convert output parameters to return values, etc. The resulting, updated interface description is the JSON object that will be "fed" to the template engine.

Both the nodebindings.tmpl.cc template and the generate.js processor are just samples - though the template might be reused as-is, you will have to tailor the generate.js script at least to the module you want to generate bindings for.

Final words

It is understood that CWrap could be improved upon in major ways. However, it will probably always require a bit of custom code for each module. As a tool for programmers, this might just be the most productive approach anyway.

2013-03-30 Jean-Pierre Gygax, practicomp.ch

npm loves you