nodejs bindings for libclang
Pull request Compare This branch is 10 commits behind tjfontaine:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


node.js module for libclang and parsing source from javascript

AST Traversal

var libclang = require('libclang');

var index = new libclang.index();
var tu = new libclang.translationunit();

tu.fromSource(idx, 'myLibrary.h', ['-I/path/to/my/project']);

tu.cursor().visitChildren(function (parent) {
  switch (this.kind) {
    case libclang.KINDS.CXCursor_FunctionDecl:
  return libclang.CXChildVisit_Continue;


Generate FFI Bindings

ffi-generate-node -f /path/to/myLibrary/header.h -l libmyLibrary

Will parse the given filename and print to standard out the resulting javascript suitable for use as a module.

  • f -- required -- The header file you wish to parse
  • l -- required -- The library FFI will use to dlopen
  • m -- optional -- The module name underwhich functions will be stored (uses library name otherwise)
  • p -- optional -- Only include functions whose name starts with the provided prefix
  • x -- optional -- Restrict to only functions declared in the given header file

It may be necessary to pass additional flags to libclang so it can better parse the header (i.e. include paths). To pass options directly to libclang use -- so ffi-generate-node knows to stop parsing arguments, the rest will be passed to libclang without modification.

ffi-generate-node -f /usr/include/ImageMagick/wand/MagickWand.h -l libMagickWand -m wand -p Magick -- $(Magick-config --cflags)

Generate FFI Bindings Programatically

var exec = require('child_process').exec;
var path = require('path');
var fs = require('fs');
var jsb = require('beautifyjs');
var generate = require('lib/generateffi').generate;

exec('llvm-config --includedir', function (fail, out, err) {
  var includedir = out.replace(/\s+$/, '');
  var result = exports.generate({
    filename: path.join(includedir, 'clang-c', 'Index.h'),
    library: 'libclang',
    prefix: 'clang_', 

  if (result.unmapped.length > 0) {
    console.log('----- UNMAPPED FUNCTIONS -----');
    console.log('----- UNMAPPED FUNCTIONS -----');

  fs.writeFileSync(path.join(__dirname, 'dynamic_clang.js'), jsb.js_beautify(result.serialized));
  var dynamic_clang = require(path.join(__dirname, 'dynamic_clang'));
  var ver = dynamic_clang.libclang.clang_getClangVersion();

Input to the generate method

  • opts.filename -- required -- the full path to the header source file to parse
  • opts.library -- required -- the library ffi should use to dlopen
  • opts.module -- optional -- the name of the module that will be exported (otherwise uses library name)
  • opts.prefix -- optional -- restrict imported functions to a given prefix
  • opts.includes -- optional -- a set of directory paths to aid type expansion
  • opts.compiler_args -- optional -- a set of clang command line options passed to the parser
  • opts.single_file -- optional -- restricts functions to only those defined in the header file
    • this does not restrict dependent types

The result from generate is an object that has two properties

  • serialized - a string representation of the bindings suitable for writing to file
  • unmapped - a set of functions that failed to map -- most likely from failure to map a type to ffi type.
    • each element is an object with following properties
    • position - -1 means the return type, otherwise the argument
    • arg - name of the type that failed to map
    • name - the name of the function that failed
    • decl - the signature of the function that failed


The native wrapper isn't completely fleshed out or free of errors. Enough is wrapped to allow for C modules to be successfully generated by lib/generateffi.js.