Nimrod ClibPP / 08.09.14

Wrapping C++ libraries in Nimrod

Traditionally a tedious process. You have to go through each class and function you want exposed, and specify its header and all its arguments, working with ugly pragmas. Take the below C++ header file for example:

// Header file
#include <iostream>

namespace pp {
	class test {

	public:
		static void output();

		int multiply(int value, int by);

		template<typename T>
		T max(T a, T b) {
		    return a > b ? a : b;
		};

		int fieldName;

		static int notherName;

	};
}

A snippet of wrapped C++ code might look something like this:

# Traditional wrapper
const test_h = "../test.hpp"
type test {.header: test_h, importcpp.} = object
    fieldName: cint
    notherName: cint

proc output(this: typedesc[test]): void {.header: test_h, importc: "pp::test::output".}
proc multiply(this: test, value, by: cint): cint {.header: test_h, importcpp.}
proc max[T](this: test, a, b: T): T {.header: test_h, importcpp.}

Introducing ClibPP

With ClibPP this process becomes much more readable and simpler. It works by parsing out each of the statements below a "class" declaration, generating code similar to the wrapper code provided above. Here's an example of what a ClibPP wrapper for the same code would look like:

# Import "test" class from C++:
import clibpp

namespace pp:
    class(test, header: "../test.hpp"):
        proc multiply[T](value, by: T): int
        proc output: void {.isstatic.}
        proc max[T](a, b: T): T
        var fieldName, notherName: int

This module also generates dummy "typedesc" parameters for static methods, so static methods can be invoked with their prefix similar to how they're invoke in C++, i.e. test.output().

Here's what using your wrapper would then look like:

# Use the "test" class from C++:
test.output()

var item: test
echo item.multiply(5, 9)
echo item.fieldName
echo item.max(2, 10)
echo item.notherName

Clone it on Github