Giter Site home page Giter Site logo

charto / nbind Goto Github PK

View Code? Open in Web Editor NEW
2.0K 50.0 126.0 1.08 MB

:sparkles: Magical headers that make your C++ library accessible from JavaScript :rocket:

License: MIT License

C++ 60.65% JavaScript 1.78% Python 0.91% TypeScript 35.98% Shell 0.48% C 0.20%
c-plus-plus node-addon asmjs nodejs emscripten typescript

nbind's Introduction

Quick start | Requirements | Features | User guide | Contributing | License

nbind flowchart

nbind is a set of headers that make your C++11 library accessible from JavaScript. With a single #include statement, your C++ compiler generates the necessary bindings without any additional tools. Your library is then usable as a Node.js addon or, if compiled to asm.js with Emscripten, directly in web pages without any plugins.

nbind works with the autogypi dependency management tool, which sets up node-gyp to compile your library without needing any configuration (other than listing your source code file names).

nbind is MIT licensed and based on templates and macros inspired by embind.

Quick start

C++ everywhere in 5 easy steps using Node.js, nbind and autogypi:

Starting point Step 1 - bind Step 2 - prepare
Original C++ code hello.cc:
#include <string>
#include <iostream>
 
struct Greeter {
  static void sayHello(
    std::string name
  ) {
    std::cout
      << "Hello, "
      << name << "!\n";
  }
};
List your classes and methods:
// Your original code here
 
// Add these below it:
 
#include "nbind/nbind.h"
 
NBIND_CLASS(Greeter) {
  method(sayHello);
}
Add scripts to package.json:
{
  "scripts": {
    "autogypi": "autogypi",
    "node-gyp": "node-gyp",
    "emcc-path": "emcc-path",
    "copyasm": "copyasm",
    "ndts": "ndts"
  }
}
Step 3 - install Step 4 - build Step 5 - use!
Run on the command line:
npm install --save \
  nbind autogypi node-gyp
 
npm run -- autogypi \
  --init-gyp \
  -p nbind -s hello.cc
Compile to native binary:
npm run -- node-gyp \
  configure build
Or to Asm.js:
npm run -- node-gyp \
  configure build \
  --asmjs=1
Call from Node.js:
var nbind = require('nbind');
var lib = nbind.init().lib;
 
lib.Greeter.sayHello('you');
Or from a web browser (see below).

The above is all of the required code. Just copy and paste in the mentioned files and prompts or take a shortcut:

git clone https://github.com/charto/nbind-example-minimal.git
cd nbind-example-minimal
npm install && npm test

See it run!

(Note: nbind-example-universal is a better starting point for development)

Requirements

You need:

And one of the following C++ compilers:

  • GCC 4.8 or above.
  • Clang 3.6 or above.
  • Emscripten 1.35.0 or above.
  • Visual Studio 2015 (the Community version is fine).

Features

nbind allows you to:

  • Use your C++ API from JavaScript without any extra effort.
    • From Node.js, Electron and web browsers (using asm.js on Chrome, Firefox and Edge).
    • On Linux, OS X and Windows.
    • Without changes to your C++ code. Simply add a separate short description at the end.
  • Distribute both native code and an asm.js fallback binary.
  • Automatically generate TypeScript .d.ts definition files from C++ code for IDE autocompletion and compile-time checks of JavaScript side code.

In more detail:

  • Export multiple C++ classes, even ones not visible from other files.
  • Export C++ methods simply by mentioning their names.
  • Auto-detect argument and return types from C++ declarations.
  • Automatically convert types and data structures between languages.
  • Call C++ methods from JavaScript with type checking.
  • Pass JavaScript callbacks to C++ and call them with any types.
  • Pass instances of compatible classes by value between languages (through the C++ stack).

The goal is to provide a stable API for binding C++ to JavaScript. All internals related to JavaScript engines are hidden away, and a single API already supports extremely different platforms.

Works on your platform

Target Development platform
Linux / OS X Windows
Native Build status Build status
Asm.js Build status Tested manually

dependency status npm version

Roadmap

More is coming! Work is ongoing to:

  • Precompile to a single native library for all versions Node.js and Electron on the same platform
    • Precompiled addons for different Node.js versions for efficiently calling the library will be provided with nbind
  • Support native Android and iPhone apps.

Future 0.x.y versions should remain completely backwards-compatible between matching x and otherwise with minor changes. Breaking changes will be listed in release notes of versions where y equals 0.

Contributing

Please report issues through Github and mention the platform you're targeting (Node.js, asm.js, Electron or something else). Pull requests are very welcome.

Warning: rebase is used within develop and feature branches (but not master).

When developing new features, writing tests first works best. If possible, please try to get them working on both Node.js and asm.js. Otherwise your pull request will get merged to Master only after maintainer(s) have fixed the other platform.

Installing Emscripten to develop for asm.js can be tricky. It will require Python 2.7 and setting paths correctly, please refer to Emscripten documentation. The bin/emcc script in this package is just a wrapper, the actual emcc compiler binary should be in your path.

You can rebuild the asm.js library and run tests as follows:

npm run clean-asm && npm run prepublish && npm run test-asm

User guide

Installing the examples

nbind examples shown in this user guide are also available to download for easier testing as follows:

Extract this zip package or run:

git clone https://github.com/charto/nbind-examples.git

Enter the examples directory and install:

cd nbind-examples
npm install

Creating your project

Once you have all requirements installed, run:

npm init
npm install --save nbind autogypi node-gyp

nbind, autogypi and node-gyp are all needed to compile a native Node.js addon from source when installing it. If you only distribute an asm.js version, you can use --save-dev instead of --save because users won't need to compile it.

Next, to run commands without installing them globally, it's practical to add them in the scripts section of your package.json that npm init just generated. Let's add an install script as well:

  "scripts": {
    "autogypi": "autogypi",
    "node-gyp": "node-gyp",
    "emcc-path": "emcc-path",
    "copyasm": "copyasm",

    "install": "autogypi && node-gyp configure build"
  }

emcc-path is needed internally by nbind when compiling for asm.js. It fixes some command line options that node-gypi generates on OS X and the Emscripten compiler doesn't like. You can leave it out if only compiling native addons.

The install script runs when anyone installs your package. It calls autogypi and then uses node-gyp to compile a native addon.

autogypi uses npm package information to set correct include paths for C/C++ compilers. It's needed when distributing addons on npm so the compiler can find header files from the nbind and nan packages installed on the user's machine. Initialize it like this:

npm run -- autogypi --init-gyp -p nbind -s hello.cc

Replace hello.cc with the name of your C++ source file. You can add multiple -s options, one for each source file.

The -p nbind means the C++ code uses nbind. Multiple -p options can be added to add any other packages compatible with autogypi.

The --init-gyp command generates files binding.gyp and autogypi.json that you should distribute with your package, so that autogypi and node-gyp will know what to do when the install script runs.

Now you're ready to start writing code and compiling.

Configuration

Refer to autogypi documentation to set up dependencies of your package, and how other packages should include it if it's a library usable directly from C++.

--asmjs=1 is the only existing configuration option for nbind itself. You pass it to node-gyp by calling it like node-gyp configure build --asmjs=1. It compiles your package using Emscripten instead of your default C++ compiler and produces asm.js output.

Calling from Node.js

First nbind needs to be initialized by calling nbind.init which takes the following optional arguments:

  • Base path under which to look for compiled binaries. Default is process.cwd() and __dirname is a good alternative.
  • Binary code exports object. Any classes from C++ API exported using nbind will be added as members. Default is an empty object. Any existing options will be seen by asm.js code and can be used to configure Emscripten output. Must follow base path (which may be set to null or undefined).
  • Node-style callback with 2 parameters:
    • Error if present, otherwise null.
    • Binary code exports object containing C++ classes.

nbind can be initialized synchronously on Node.js and asynchronously on browsers and Node.js. Purely synchronous is easier but not as future-proof:

var nbind = require('nbind');
var lib = nbind.init().lib;

// Use the library.

Using a callback also supports asynchronous initialization:

var nbind = require('nbind');

nbind.init(function(err, binding) {
  var lib = binding.lib;

  // Use the library.
});

The callback passed to init currently gets called synchronously in Node.js and asynchronously in browsers. To avoid releasing zalgo you can for example wrap the call in a bluebird promise:

var bluebird = require('bluebird');
var nbind = require('nbind');

bluebird.promisify(nbind.init)().then(function(binding) {
  var lib = binding.lib;

  // Use the library.
});

Using nbind headers

There are two possible files to include:

  • nbind/api.h for using types from the nbind namespace such as JavaScript callbacks inside your C++ code.
    • #include before your own class definitions.
    • Causes your code to depend on nbind.
  • nbind/nbind.h for exposing your C++ API to JavaScript.
    • #include after your own class definitions to avoid accidentally invoking its macros.
    • The header automatically hides itself if not targeting Node.js or asm.js.
    • Safe to use in any projects.

Use #include "nbind/nbind.h" at the end of your source file with only the bindings after it. The header defines macros with names like construct and method that may otherwise break your code or conflict with other headers.

It's OK to include nbind/nbind.h also when not targeting any JavaScript environment. node-gyp defines a BUILDING_NODE_EXTENSION macro and Emscripten defines an EMSCRIPTEN macro so when those are undefined, the include file does nothing.

Use #include "nbind/api.h" in your header files to use types in the nbind namespace if you need to report errors without throwing exceptions, or want to pass around callbacks or objects.

You can use an #ifdef NBIND_CLASS guard to skip your nbind export definitions when the headers weren't loaded.

Example that uses an nbind callback in C++ code:

1-headers.cc

#include <string>
#include <iostream>

// For nbind::cbFunction type.
#include "nbind/api.h"

class HeaderExample {

public:

  static void callJS(nbind::cbFunction &callback) {
    std::cout << "JS says: " << callback.call<std::string>(1, 2, 3);
  }

};

// For NBIND_CLASS() and method() macros.
#include "nbind/nbind.h"

#ifdef NBIND_CLASS

NBIND_CLASS(HeaderExample) {
  method(callJS);
}

#endif

Example used from JavaScript:

1-headers.js

var nbind = require('nbind');

var lib = nbind.init().lib;

lib.HeaderExample.callJS(function(a, b, c) {
  return('sum = ' + (a + b + c) + '\n');
});

Run the example with node 1-headers.js after installing. It prints:

JS says: sum = 6

Functions

Functions not belonging to any class are exported inside an NBIND_GLOBAL block with a macro call function(functionName); which takes the name of the function as an argument (without any quotation marks). The C++ function gets exported to JavaScript with the same name, or it can be renamed by adding a second argument (with quotation marks): function(cppFunctionName, "jsExportedName");

If the C++ function is overloaded, multifunction macro must be used instead. See overloaded functions.

Note: you cannot put several function(...); calls on the same line! Otherwise you'll get an error about redefining a symbol.

Example:

6-functions.cc

#include <iostream>

void sayHello(std::string name) {
  std::cout << "Hello, " << name << "!\n";
}

#include "nbind/nbind.h"

NBIND_GLOBAL() {
  function(sayHello);
}

Example used from JavaScript:

6-functions.js

var nbind = require('nbind');
var lib = nbind.init().lib;

lib.sayHello('you');

Classes and constructors

The NBIND_CLASS(className) macro takes the name of your C++ class as an argument (without any quotation marks), and exports it to JavaScript using the same name. It's followed by a curly brace enclosed block of method exports, as if it was a function definition.

The class can be renamed on the JavaScript side by passing a string as a second argument. This is especially useful for binding a template class specialization with a more reasonable name: NBIND_CLASS(Data<int>, "IntData")

Constructors are exported with a macro call construct<types...>(); where types is a comma-separated list of arguments to the constructor, such as int, int. Calling construct multiple times allows overloading it, but each overload must have a different number of arguments.

Constructor arguments are the only types that nbind cannot detect automatically.

Example with different constructor argument counts and types:

2-classes.cc

#include <iostream>

class ClassExample {

public:

  ClassExample() {
    std::cout << "No arguments\n";
  }
  ClassExample(int a, int b) {
    std::cout << "Ints: " << a << " " << b << "\n";
  }
  ClassExample(const char *msg) {
    std::cout << "String: " << msg << "\n";
  }

};

#include "nbind/nbind.h"

NBIND_CLASS(ClassExample) {
  construct<>();
  construct<int, int>();
  construct<const char *>();
}

Example used from JavaScript:

2-classes.js

var nbind = require('nbind');

var lib = nbind.init().lib;

var a = new lib.ClassExample();
var b = new lib.ClassExample(42, 54);
var c = new lib.ClassExample("Don't panic");

Run the example with node 2-classes.js after installing. It prints:

No arguments
Ints: 42 54
String: Don't panic

Inheritance

When a C++ class inherits another, the inherit macro can be used to allow calling parent class methods on the child class, or passing child class instances to C++ methods expecting parent class instances.

Internally JavaScript only has prototype-based single inheritance while C++ supports multiple inheritance. To simulate it, nbind will use one parent class as the child class prototype, and copy the contents of the other parents to the prototype. This has otherwise the same effect, except the JavaScript instanceof operator will return true for only one of the parent classes.

Example:

NBIND_CLASS(Child) {
    inherit(FirstParent);
    inherit(SecondParent);
}

Methods and properties

Methods are exported inside an NBIND_CLASS block with a macro call method(methodName); which takes the name of the method as an argument (without any quotation marks). The C++ method gets exported to JavaScript with the same name.

If the C++ method is overloaded, multimethod macro must be used instead. See overloaded functions.

Properties should be accessed through getter and setter functions.

Data types of method arguments and its return value are detected automatically so you don't have to specify them. Note the supported data types because using other types may cause compiler errors that are difficult to understand.

If the method is static, it becomes a property of the JavaScript constructor function and can be accessed like className.methodName(). Otherwise it becomes a property of the prototype and can be accessed like obj = new className(); obj.methodName();

Example with a method that counts a cumulative checksum of ASCII character values in strings, and a static method that processes an entire array of strings:

3-methods.cc

#include <string>
#include <vector>

class MethodExample {

public:

  unsigned int add(std::string part) {
    for(char &c : part) sum += c;

    return(sum);
  }

  static std::vector<unsigned int> check(std::vector<std::string> list) {
    std::vector<unsigned int> result;
    MethodExample example;

    for(auto &&part : list) result.push_back(example.add(part));

    return(result);
  }

  unsigned int sum = 0;

};

#include "nbind/nbind.h"

NBIND_CLASS(MethodExample) {
  construct<>();

  method(add);
  method(check);
}

Example used from JavaScript, first calling a method in a loop from JS and then a static method returning an array:

3-methods.js

var nbind = require('nbind');

var lib = nbind.init().lib;

var parts = ['foo', 'bar', 'quux'];

var checker = new lib.MethodExample();

console.log(parts.map(function(part) {
  return(checker.add(part));
}));

console.log(lib.MethodExample.check(parts));

Run the example with node 3-methods.js after installing. It prints:

[ 324, 633, 1100 ]
[ 324, 633, 1100 ]

The example serves to illustrate passing data. In practice, such simple calculations are faster to do in JavaScript rather than calling across languages because copying data is quite expensive.

Overloaded functions

The function() and method() macroes cannot distinguish between several overloaded versions of the same function or method, causing an error. In this case the multifunction() and multimethod() macroes must be used.

Their second parameter is a list of argument types wrapped in an args() macro to select a single overloaded version.

For example consider an overloaded method:

void test(unsigned int x) const;
void test(unsigned int x, unsigned int y) const;

In bindings, one of the versions needs to be explicitly selected. The second of the two would be referenced like:

multimethod(test, args(unsigned int, unsigned int));

As always, the return type and method constness are autodetected.

For calling from JavaScript, additionally each overload needs to have a distinct name. For renaming an overload JavaScript will see, the binding code is like:

multimethod(test, args(unsigned int, unsigned int), "test2");

You can then write a JavaScript wrapper to inspect arguments and select which overload to call. The reason for this is, that nbind binds a JavaScript property to a single C++ function pointer, which wraps one overloaded version of the function with type conversion code.

Otherwise, it would need to generate a new C++ function that also checks the arguments. This would result in a larger native binary without any speed advantage.

Getters and setters

Property getters are exported inside an NBIND_CLASS block with a macro call getter(getterName) with the name of the getter method as an argument. nbind automatically strips a get/Get/get_/Get_ prefix and converts the next letter to lowercase, so for example getX and get_x both would become getters of x to be accessed like obj.x

Property setters are exported together with getters using a macro call getset(getterName, setterName) which works much like getter(getterName) above. Both getterName and setterName are mangled individually so you can pair getX with set_x if you like. From JavaScript, ++obj.x would then call both of them to read and change the property.

Example class and property with a getter and setter:

4-getset.cc

class GetSetExample {

public:

  void setValue(int value) { this->value = value; }
  int getValue() { return(value); }

private:

  int value = 42;

};

#include "nbind/nbind.h"

NBIND_CLASS(GetSetExample) {
  construct<>();

  getset(getValue, setValue);
}

Example used from JavaScript:

4-getset.js

var nbind = require('nbind');

var lib = nbind.init().lib;

var obj = new lib.GetSetExample();

console.log(obj.value++); // 42
console.log(obj.value++); // 43

Run the example with node 4-getset.js after installing.

Passing data structures

nbind supports automatically converting between JavaScript arrays and C++ std::vector or std::array types. Just use them as arguments or return values in C++ methods.

Note that data structures don't use the same memory layout in both languages, so the data always gets copied which takes more time for more data. For example the strings in an array of strings also get copied, one character at a time. In asm.js data is copied twice, first to a temporary space using a common format both languages can read and write.

Callbacks

Callbacks can be passed to C++ methods by simply adding an argument of type nbind::cbFunction & to their declaration.

They can be called with any number of any supported types without having to declare in any way what they accept. The JavaScript code will receive the parameters as JavaScript variables to do with them as it pleases.

A callback argument arg can be called like arg("foobar", 42); in which case the return value is ignored. If the return value is needed, the callback must be called like arg.call<type>("foobar", 42); where type is the desired C++ type that the return value should be converted to. This is because the C++ compiler cannot otherwise know what the callback might return.

Warning: while callbacks are currently passed by reference, they're freed after the called C++ function returns! That's intended for synchronous functions like Array.map which calls a callback zero or more times and then returns. For asynchronous functions like setTimeout which calls the callback after it has returned, you need to copy the argument to a new nbind::cbFunction and store it somewhere.

Using objects

C++ objects can be passed to and from JavaScript using different parameter and return types in C++ code:

  • by reference using pointers or references (optionally const)
  • by value

Note: currently passing objects by pointer on Node.js requires the class to have a "copy constructor" initializing itself from a pointer. This will probably be fixed later.

Returned pointers and references can be const, in which case calling their non-const methods or passing them as non-const parameters will throw an error. This prevents causing undefined behaviour corresponding to C++ code that wouldn't even compile.

Using pointers and references is particularly:

  • dangerous because the pointer may become invalid without JavaScript noticing it.
  • annoying in asm.js because browsers give no access to the garbage collector, so memory may leak when pointers become garbage without C++ noticing it. Smart pointers are not supported until a workaround for this is implemented.

Passing data by value using value objects solves both issues. They're based on a toJS function on the C++ side and a fromJS function on the JavaScript side. Both receive a callback as an argument, and calling it with any parameters calls the constructor of the equivalent type in the other language.

The callback on the C++ side is of type nbind::cbOutput. Value objects are passed through the C++ stack to and from the exported function. nbind uses C++11 move semantics to avoid creating some additional copies on the way.

The equivalent JavaScript constructor must be registered on the JavaScript side by calling binding.bind('CppClassName', JSClassName) so that nbind knows which types to translate between each other.

Example with a class Coord used as a value object, and a class ObjectExample which uses objects passed by values and references:

5-objects.cc

#include <iostream>

#include "nbind/api.h"

class Coord {

public:

  Coord(signed int x = 0, signed int y = 0) : x(x), y(y) {}
  explicit Coord(const Coord *other) : x(other->x), y(other->y) {}

  void toJS(nbind::cbOutput output) {
    output(x, y);
  }

  signed int getX() { std::cout << "Get X\n"; return(x); }
  signed int getY() { std::cout << "Get Y\n"; return(y); }

  void setX(signed int x) { this->x = x; }
  void setY(signed int y) { this->y = y; }

  signed int x, y;

};

class ObjectExample {

public:

  static void showByValue(Coord coord) {
    std::cout << "C++ value " << coord.x << ", " << coord.y << "\n";
  }

  static void showByRef(Coord *coord) {
    std::cout << "C++ ref " << coord->x << ", " << coord->y << "\n";
  }

  static Coord getValue() {
    return(Coord(12, 34));
  }

  static Coord *getRef() {
    static Coord coord(56, 78);
    return(&coord);
  }

};

#include "nbind/nbind.h"

NBIND_CLASS(Coord) {
  construct<>();
  construct<const Coord *>();
  construct<signed int, signed int>();

  getset(getX, setX);
  getset(getY, setY);
}

NBIND_CLASS(ObjectExample) {
  method(showByValue);
  method(showByRef);
  method(getValue);
  method(getRef);
}

Example used from JavaScript:

5-objects.js

var nbind = require('nbind');

var binding = nbind.init();
var lib = binding.lib;

function Coord(x, y) {
  this.x = x;
  this.y = y;
}

Coord.prototype.fromJS = function(output) {
  output(this.x, this.y);
}

Coord.prototype.show = function() {
  console.log('JS value ' + this.x + ', ' + this.y);
}

binding.bind('Coord', Coord);

var value1 = new Coord(123, 456);
var value2 = lib.ObjectExample.getValue();
var ref = lib.ObjectExample.getRef();

lib.ObjectExample.showByValue(value1);
lib.ObjectExample.showByValue(value2);
value1.show();
value2.show();

lib.ObjectExample.showByRef(ref);
console.log('JS ref ' + ref.x + ', ' + ref.y);

Run the example with node 5-objects.js after installing. It prints:

C++ value 123, 456
C++ value 12, 34
JS value 123, 456
JS value 12, 34
C++ ref 56, 78
Get X
Get Y
JS ref 56, 78

Type conversion

Parameters and return values of function calls between languages are automatically converted between equivalent types:

JavaScript C++
number (un)signed char, short, int, long
number float, double
number or bignum (un)signed long, long long
boolean bool
string const (unsigned) char *
string std::string
Array std::vector<type>
Array std::array<type, size>
Function nbind::cbFunction
(only as a parameter)
See Callbacks
nbind-wrapped pointer Pointer or reference to an
instance of any bound class
See Using objects
Instance of any prototype
(with a fromJS method)
Instance of any bound class
(with a toJS method)
See Using objects
ArrayBuffer(View), Int*Array
or Buffer
nbind::Buffer struct
(data pointer and length)
See Buffers

Type conversion is customizable by passing policies as additional arguments to construct, function or method inside an NBIND_CLASS or NBIND_GLOBAL block. Currently supported policies are:

  • nbind::Nullable() allows passing null as an argument when a C++ class instance is expected. The C++ function will then receive a nullptr.
  • nbind::Strict() enables stricter type checking. Normally anything in JavaScript can be converted to number, string or boolean when expected by a C++ function. This policy requires passing the exact JavaScript type instead.

Type conversion policies are listed after the method or function names, for example:

NBIND_CLASS(Reference) {
    method(reticulateSplines, "reticulate", nbind::Nullable());
    method(printString, nbind::Strict());
}

Buffers

Transferring large chunks of data between languages is fastest using typed arrays or Node.js buffers in JavaScript. Both are accessible from C++ as plain blocks of memory if passed in through the nbind::Buffer data type which has the methods:

  • data() returns an unsigned char * pointing to a block of memory also seen by JavaScript.
  • length() returns the length of the block in bytes.
  • commit() copies data from C++ back to JavaScript (only needed with Emscripten).

This is especially useful for passing canvas.getContext('2d').getImageData(...).data to C++ and drawing to an on-screen bitmap when targeting Emscripten or Electron.

Example:

#include "nbind/api.h"

void range(nbind::Buffer buf) {
  size_t length = buf.length();
  unsigned char *data = buf.data();

  if(!data || !length) return;

  for(size_t pos = 0; pos < length; ++pos) {
    data[pos] = pos;
  }

  buf.commit();
}

#include "nbind/nbind.h"

NBIND_GLOBAL() {
  function(range);
}

Example used from JavaScript:

var nbind = require('nbind');
var lib = nbind.init().lib;

var data = new Uint8Array(16);
lib.range(data);

console.log(data.join(' '));

It prints:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

64-bit integers

Normally C++ 64-bit integer types are first converted to double and then to JavaScript number which can only hold 53 bits of precision, but it's possible to preserve all bits by using a bignum class. It should have a constructor taking the following arguments:

  • Integer containing 32 bits from the least important half.
  • Integer containing 32 bits from the most important half.
  • Boolean, true if the number is negative.

It should also have a fromJS function which takes a callback, and calls it with those same arguments to pass the data back to C++ when needed.

An example implementation also capable of printing 64-bit numbers to strings in bases 2, 4, 10 and 16 is included.

Error handling

You can use the NBIND_ERR("message here"); macro to report an error before returning from C++ (#include "nbind/api.h" first). It will be thrown as an error on the JavaScript side (C++ environments like Emscripten may not support throwing exceptions, but the JavaScript side will).

Publishing on npm

Make sure your package.json file has at least the required emcc-path and install scripts:

  "scripts": {
    "emcc-path": "emcc-path",

    "install": "autogypi && node-gyp configure build"
  }

The dependencies section should have at least:

  "dependencies": {
    "autogypi": "^0.2.2",
	"nbind": "^0.2.1",
    "node-gyp": "^3.3.1"
  }

Your package should also include binding.gyp and autogypi.json files.

Shipping an asm.js fallback

nbind-example-universal is a good minimal example of compiling a native Node.js addon if possible, and otherwise using a pre-compiled asm.js version.

It has two temporary build directories build/native and build/asmjs, for compiling both versions. nbind provides a binary copyasm that can then be used to copy the compiled asm.js library into a nicer location for publishing inside the final npm package.

Note that the native version should be compiled in the install script so it runs for all users of the package, and the asm.js version should be compiled in the prepublish script so it gets packaged in npm for usage without the Emscripten compiler. See the example package.json file.

Using in web browsers

nbind-example-universal is a good minimal example also of calling compiled asm.js code from inside web browsers. The simplest way to get nbind working is to add these scripts in your HTML code as seen in the example index.html:

<script src="nbind.js"></script>

<script>
  nbind.init(function(err, binding) {
    var lib = binding.lib;

    // Use the library.
  });
</script>

Make sure to fix the path to nbind.js on the first line if necessary.

Using with TypeScript

nbind has a fully typed API for interacting with C++ code and it can also automatically generate .d.ts files for your C++ classes and functions. This gives you effortless bindings with compile time type checking for calls from JavaScript to Node.js addons and asm.js modules.

All you have to do is compile your C++ code and run the included ndts tool to create the type definitions:

npm run -- node-gyp configure build
npm run -s -- ndts . > lib-types.d.ts

When run in this way, the first argument of ndts is a path from the package root to the binding.gyp file. Typically the file is in the root so the correct path is .

Now you can load the C++ code from TypeScript in three different ways. First import nbind (which also loads the C++ code) and types generated by ndts:

import * as nbind from 'nbind';
import * as LibTypes from './lib-types';

Then choose your favorite way to initialize it:

Purely synchronous:

const lib = nbind.init<typeof LibTypes>().lib;

// Use the library.

Asynchronous-aware:

nbind.init((err: any, binding: nbind.Binding<typeof LibTypes>) => {
  const lib = binding.lib;

  // Use the library.
});

Promise-based:

import * as bluebird from 'bluebird';

bluebird.promisify(nbind.init)().then((binding: nbind.Binding<typeof LibTypes>) => {
  const lib = binding.lib;

  // Use the library.
});

Note how there is a type argument <typeof LibTypes> for the init call in all of the examples. It defines types of binding.lib contents, which coming from C++ are otherwise unknown to the TypeScript compiler. You can import the types from a file generated by ndts or just use <any> to disable typing.

For example if you have a C++ class:

struct C : public A, public B {
    A *getA();

    static uint32_t reticulate();
};

And bind it like:

NBIND_CLASS(C) {
    inherit(A);
    inherit(B);

    construct<>();

    method(reticulate);

    getter(getA);
}

ndts will generate the following typings:

export interface _C extends A, B {}
export var _C: { new(): _C };

export class C extends _C {
    /** C(); */
    constructor();

    /** static uint32_t reticulate(); */
    static reticulate(): number;

    /** A * a; -- Read-only */
    a: A;
}

The additional interface _C is generated in this case to support multiple inheritance, because C extends both A and B.

All the tests are written in TypeScript so if you run:

git clone https://github.com/charto/nbind.git
cd nbind
npm install
npm test

You can then open test/test.ts in a TypeScript IDE and see the generated typings in action.

Binding plain C

nbind generates bindings using C++ templates for compile-time introspection of argument and return types of functions and methods.

Since plain C doesn't have templates, there's no standard way to have a C compiler generate new wrapper code for type conversion and output type information available at run-time.

The easiest way to use nbind with C is to write a C++ wrapper calling the C code, and use nbind with that.

Mapping idiomatic C to JavaScript classes may require some manual work, since it's common to reinvent new ways to do object-oriented programming, usually by using structs as classes and simulating methods by passing struct pointers to functions. C++ classes and methods should be used for these.

A good example is libui-node which uses nbind to generate bindings for libui, mainly a C library.

Binding external libraries

If you have external library source code, you should compile it separately into a library first, and then link your Node.js addon with it. If the library has an installation script and the addon is only intended for your own use or other users are willing to do some extra steps, it's easiest to install the library globally first.

For best user experience, libui-node is an example of distributing an external library together with your package.

For creating the actual bindings, see for example this and this message and a tutorial for getting the vg library working.

Debugging

In the browser it can be difficult to stop and debug at the correct spot in optimized C++ code. nbind provides an _nbind_debug() function in api.h that you can call from C++ to invoke the browser's debugger when using asm.js.

For debugging a Node.js addon, if you would normally test it like node test.js, you can instead use gdb node and type run test.js in the GDB prompt. Then in case of a crash, it will show where it happened, inspect the stack etc.

You should also modify nbind.gypi (inside nbind's src directory) and possibly your own binding.gyp, to remove any -O? flags and instead add a -g flag, then remove the build directory and recompile. This allows GDB to show much more information.

Alternatives

Very similar:

Less similar:

Authors

  • Juha Järvi, befungedomain

License

The MIT License

Copyright (c) 2014-2017 BusFaster Ltd

nbind's People

Contributors

arcanis avatar dasa avatar isnit0 avatar jjrv avatar orta avatar parro-it avatar shawwn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nbind's Issues

Add missing features

Emscripten target is still missing one feature:

  • Inheritance between C++ classes and automatic upcasting.
  • Const and non-const pointers as argument and return types.
  • Const and non-const references as argument and return types.
  • Smart pointers as argument and return types.
  • Conversion between JavaScript arrays and C++ vectors.
  • Plain functions (like static methods but outside any class).
  • Destroy method, freeing the C++ instance and invalidating the wrapper object's internal pointer.
  • Support passing int64_t and uint64_t losslessly to a bignum object with hi, lo parts and a toString method.

long or unsigned long not supported

I get an error if I use long or unsigned long argument:

../node_modules/nbind/include/nbind/v8/ValueObj.h: In instantiation of ‘static nbind::WireType nbind::BindingType<ArgType>::toWireType(ArgType) [with ArgType = long int; nbind::WireType = v8::Local<v8::Value>]’:
../node_modules/nbind/include/nbind/v8/Caller.h:76:63:   required from ‘static nbind::WireType nbind::MethodResultConverter<ReturnType>::toWireType(ReturnType&&, Bound&) [with Bound = UiColorButton; ReturnType = long int; nbind::WireType = v8::Local<v8::Value>]’
../node_modules/nbind/include/nbind/v8/Caller.h:94:3:   required from ‘static nbind::WireType nbind::Caller<ReturnType, nbind::TypeList<Args ...> >::callMethod(Bound&, MethodType, NanArgs&) [with Bound = UiColorButton; MethodType = long int (UiColorButton::*)(); NanArgs = const Nan::FunctionCallbackInfo<v8::Value>; ReturnType = long int; Args = {}; nbind::WireType = v8::Local<v8::Value>]’
../node_modules/nbind/include/nbind/signature/MethodSignature.h:34:3:   required from ‘static void nbind::MethodSignature<PtrType, Bound, ReturnType, Args>::callInner(V8Args&, NanArgs&, Bound*) [with V8Args = const Nan::FunctionCallbackInfo<v8::Value>; NanArgs = const Nan::FunctionCallbackInfo<v8::Value>; PtrType = long int (UiColorButton::*)(); Bound = UiColorButton; ReturnType = long int; Args = {}]’
../node_modules/nbind/include/nbind/signature/BaseSignature.h:198:46:   required from ‘static void nbind::TemplatedBaseSignature<Signature, ReturnType, Args>::callInnerSafely(V8Args&, NanArgs&) [with Bound = UiColorButton; V8Args = const Nan::FunctionCallbackInfo<v8::Value>; NanArgs = const Nan::FunctionCallbackInfo<v8::Value>; Signature = nbind::MethodSignature<long int (UiColorButton::*)(), UiColorButton, long int>; ReturnType = long int; Args = {}]’
../node_modules/nbind/include/nbind/signature/MethodSignature.h:38:53:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
../node_modules/nbind/include/nbind/signature/MethodSignature.h:16:7:   required from ‘static Signature& nbind::TemplatedBaseSignature<Signature, ReturnType, Args>::getInstance() [with Signature = nbind::MethodSignature<long int (UiColorButton::*)(), UiColorButton, long int>; ReturnType = long int; Args = {}]’
../node_modules/nbind/include/nbind/BindDefiner.h:77:28:   required from ‘void nbind::BindDefiner<Bound>::addMethod(const char*, MethodType) [with Signature = nbind::MethodSignature<long int (UiColorButton::*)(), UiColorButton, long int>; MethodType = long int (UiColorButton::*)(); Bound = UiColorButton]’
../node_modules/nbind/include/nbind/BindDefiner.h:86:12:   required from ‘void nbind::BindDefiner<Bound>::addMethodMaybeConst(const char*, ReturnType (Bound::*)(Args ...)) [with Signature = nbind::MethodSignature; ReturnType = long int; Args = {}; Bound = UiColorButton]’
../node_modules/nbind/include/nbind/BindDefiner.h:123:22:   required from ‘nbind::BindDefiner<Bound>& nbind::BindDefiner<Bound>::function(const char*, MethodType, Policies ...) [with MethodType = long int (UiColorButton::*)(); Policies = {}; Bound = UiColorButton]’
../src/UiColorButton.cc:45:2:   required from ‘BindInvokerUiColorButton<Bound>::BindInvokerUiColorButton() [with Bound = UiColorButton]’
../src/UiColorButton.cc:41:1:   required from here
../node_modules/nbind/include/nbind/v8/ValueObj.h:59:3: error: request for member ‘toJS’ in ‘arg’, which is of non-class type ‘long int’
   arg.toJS(construct);

It appear nbind does not recognized as a basic type it and try to implement it as object, requiring a toJS member to convert it.

I get this while implmenting UiColorButton on libui-node on this branch

Enumerable properties

It seems that getters aren't currently enumerable, is it the expected behaviour? Is there a way to make them enumerable? I've tried the following, but got a Type Mismatch error:

Object.defineProperty(lib.Point.prototype, 'row', {
    enumerable: true
});

Object.defineProperty(lib.Point.prototype, 'column', {
    enumerable: true
});

Question on C Compatibility

I understand there are some big differences between C and C++.

So I am not trying to say "please make this C compatible".

I'm just curious what the major differences are, if there are difficulties with C that don't exists for C++, etc. As well, what you would recommend for achieving similar with C libs.

Thanks, this looks really cool, excited to try it out.

Callbacks cannot be copied on the v8 codepath

The following lines do not compile with the v8 codepath:

nbind::cbFunction fn; // no matching function for call to ‘nbind::cbFunction::cbFunction()’
fn = otherFnFunction; // use of deleted function ‘nbind::cbFunction& nbind::cbFunction::operator=(const nbind::cbFunction&)’

I've found this line in the documentation that seems to imply that this is a bug (plus, it work fine on the emscripten codepath):

Warning: while callbacks are currently passed by reference, they're freed after the called C++ function returns! That's intended for synchronous functions like Array.map which calls a callback zero or more times and then returns. For asynchronous functions like setTimeout which calls the callback after it has returned, you need to copy the argument to a new nbind::cbFunction and store it somewhere.

Multiple native modules failure.

I have written two native modules using nbind.
Each module is exposed via an index.js file like so:

var nbind = require('nbind');

var binding = nbind.init(__dirname);
var lib = binding.lib;

module.exports = lib

When I require one of them, they both work as expected. Whenever I require both of them at the same time, hell breaks loose.

binaryTreesCPP = require('./benchmarks/binary-trees/native-cpp');
binaryTreesC = require('./benchmarks/binary-trees/native-c');

causes:

$ node bench.js 
/home/ken/Desktop/node-benchmarks/benchmarks/binary-trees/native-c/node_modules/nbind/dist/nbind.js:145
    binding.bind = lib.NBind.bind_value;
                            ^

TypeError: Cannot read property 'bind_value' of undefined
    at initNode (/home/ken/Desktop/node-benchmarks/benchmarks/binary-trees/native-c/node_modules/nbind/dist/nbind.js:145:29)
    at /home/ken/Desktop/node-benchmarks/benchmarks/binary-trees/native-c/node_modules/nbind/dist/nbind.js:114:13
    at findCompiledModule (/home/ken/Desktop/node-benchmarks/benchmarks/binary-trees/native-c/node_modules/nbind/dist/nbind.js:78:13)
    at find (/home/ken/Desktop/node-benchmarks/benchmarks/binary-trees/native-c/node_modules/nbind/dist/nbind.js:92:13)
    at Object.init (/home/ken/Desktop/node-benchmarks/benchmarks/binary-trees/native-c/node_modules/nbind/dist/nbind.js:103:5)
    at Object.<anonymous> (/home/ken/Desktop/node-benchmarks/benchmarks/binary-trees/native-c/index.js:3:21)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)

Node.js 6.0.0 complains about deprecated v8::FunctionTemplate::Set() with non-primitive values

When I run some C++ nbind-ed code with node v5.10.0, everything works fine.
But node v6.0.0 returns several warnings:

(node) v8::FunctionTemplate::Set() with non-primitive values is deprecated
(node) and will stop working in the next major release.

==== JS stack trace =========================================

Security context: 000001CC471C9FC9 <JS Object>#0#
    1: .node [module.js:568] [pc=000003D81714F664] (this=00000230B60B7749 <an Object with map 000000C2A2317241>#1#,module=00000230B60D74A9 <a Module with map 000000C2A2317819>#2#,filename=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    2: load [module.js:456] [pc=000003D81713AAF2] (this=00000230B60D74A9 <a Module with map 000000C2A2317819>#2#,filename=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    3: tryModuleLoad(aka tryModuleLoad) [module.js:415] [pc=000003D81713A61D] (this=000001CC47104189 <undefined>,module=00000230B60D74A9 <a Module with map 000000C2A2317819>#2#,filename=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    4: _load [module.js:407] [pc=000003D817135A62] (this=00000230B6075361 <JS Function Module (SharedFunctionInfo 00000112075282E1)>#3#,request=00000230B60D7001 <String[60]: build\Release\nbind.node>,parent=00000230B60C6571 <a Module with map 000000C2A2317819>#4#,isMain=000001CC47104299 <false>)
    5: require [module.js:466] [pc=000003D817144E73] (this=00000230B60C6571 <a Module with map 000000C2A2317819>#4#,path=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    6: require(aka require) [internal/module.js:20] [pc=000003D817144BA6] (this=000001CC47104189 <undefined>,path=00000230B60D7001 <String[60]: build\Release\nbind.node>)
    7: init [node_modules\nbind\index.js:96] [pc=000003D81714C458] (this=00000230B60CB051 <an Object with map 000000C2A2319659>#5#,basePath=00000230B60CB199 <String[42]: src/..>)
    8: /* anonymous */ [src\test.js:3] [pc=000003D8171443C1] (this=000001CC471E9141 <JS Global Object>#6#)
    9: /* anonymous */ [src\test.js:14] [pc=000003D817144678] (this=00000230B60BB1A9 <an Object with map 00000241D4F07B71>#7#,exports=00000230B60BB1A9 <an Object with map 00000241D4F07B71>#7#,require=00000230B60BD8F9 <JS Function require (SharedFunctionInfo 0000011207558DB9)>#8#,module=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,__filename=00000230B60BB011 <String[47]: src\test.js>,__dirname=00000230B60BD821 <String[39]: src>)
   10: _compile [module.js:541] [pc=000003D817144064] (this=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,content=00000230B60BD1A9 <String[361]\: (function(){\r\n  var nbind = require('nbind');\r\n      nbind.init(__dirname+"/..");\r\n  var WSM = nbind.module.ServerWSMWrapper;\r\n\r\n  function Pair(first, second) {\r\n      this.first  = first;\r\n      this.second = second;\r\n  }\r\n  nbind.bind('IntPair', Pair);\r\n\r\n  const ver = WSM.GetWSMVersion(); \r\n  console.log("WSM version "+ ver.first +"."+ ver.second);\r\n})();>,filename=00000230B60BB011 <String[47]: src\test.js>)
   11: .js [module.js:550] [pc=000003D81713CB8B] (this=00000230B60B7749 <an Object with map 000000C2A2317241>#1#,module=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,filename=00000230B60BB011 <String[47]: src\test.js>)
   12: load [module.js:456] [pc=000003D81713AAF2] (this=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,filename=00000230B60BB011 <String[47]: src\test.js>)
   13: tryModuleLoad(aka tryModuleLoad) [module.js:415] [pc=000003D81713A61D] (this=000001CC47104189 <undefined>,module=00000230B60BB0B1 <a Module with map 000000C2A2317819>#9#,filename=00000230B60BB011 <String[47]: src\test.js>)
   14: _load [module.js:407] [pc=000003D817135A62] (this=00000230B6075361 <JS Function Module (SharedFunctionInfo 00000112075282E1)>#3#,request=00000230B606FD39 <String[47]: src\test.js>,parent=000001CC47104101 <null>,isMain=000001CC47104231 <true>)
   15: runMain [module.js:575] [pc=000003D81713552A] (this=00000230B6075361 <JS Function Module (SharedFunctionInfo 00000112075282E1)>#3#)
   16: startup(aka startup) [node.js:159] [pc=000003D817040A3E] (this=000001CC47104189 <undefined>)
   17: /* anonymous */(aka /* anonymous */) [node.js:444] [pc=000003D81703E6D2] (this=000001CC47104101 <null>,process=000001CC471E52E1 <a process with map 00000241D4F10D89>#10#)
=====================

How can this be fixed? If I hade more insight of how nbind works, I would love to try fixing this...

compilation fails

Hi,
Is is possible to prebuild c++ file without node present? That is - to have my working c++ project, and just to include nbind/nbind.h like in examples, and then just compile using g++ or windows studio and have a working exec? I'm trying to do this with visual studio 2015, but

NBIND_GLOBAL() { //explicit type is missing error
	function(sayHello); //identifier NBIND_FUNCTION is undefined error
}

there is also error with callback function...
I'm interested in doing it this way, since I plan to use node in embedded enviroment, and it complicated to cross compile.
Maybe I'm just missing something trivial?

Support TypeScript

nbind should automatically generate TypeScript .d.ts definition files and Closure Compiler externs from the C++ code. This should be done with a simple interface to query internal typing data, and an external NPM package that can read such data and output bindings in either format. This should work regardless of whether the C++ code was compiled using Emscripten or natively to a Node.js plugin. This is scheduled after Emscripten support. The separate tasks are:

  • Read type information from Node.js module.
  • Same, but from Emscripten.
  • Output TypeScript definitions.

Interface to jxcore

Thanks for publishing this project which you announced in nodejs/nan#437! It definitely looks much easier than following nodejs.org/api/addons.html and I can see some advantages over existing NAN API as well. The JXCore project supports multiple JS engines (currently V8 and SpiderMonkey) which is essential for supporting multiple mobile platforms. They made their own JS native interface as documented in https://github.com/jxcore/jxcore/tree/master/doc/native and it looks like a major feat for supporting multiple JS engines. It would be great if this project would support JXCore as well.

I am planning look into this in the next week or so, will keep you posted. I am raising this issue in case any others will have input.

ndts is failing

I've installed nbind-example-minimal and npm test works, but I get this error when I run npm run -- ndts .

/Users/dasa/Projects/nbind/nbind-example-minimal/node_modules/nbind/dist/reflect.js:144
        this.globalScope.methodList.sort(compareName);
                        ^

TypeError: Cannot read property 'methodList' of undefined
    at new Reflect (/Users/dasa/Projects/nbind/nbind-example-minimal/node_modules/nbind/dist/reflect.js:144:25)
    at Object.<anonymous> (/Users/dasa/Projects/nbind/nbind-example-minimal/node_modules/nbind/bin/ndts.js:6:15)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:420:7)
    at startup (bootstrap_node.js:139:9)

How to use nbind with header *.hpp and source *.cpp files?

Hi everyone,

I am wondering how to use nbind having a C++ code structured in header files (ending with .hpp) and source files (ending with .cpp).
One major question is, how to let node-gyp know, when or how to use my header file?

My second question is where to put the nbind stuff:
The class declaration is in my hpp file:

#include
#include

class Greeter {
public:
static void sayHello(std::string name);
};

The implementation in my cpp file:

#include "hello.hpp"

static void sayHello(std::string name) {
std::cout<< "Hello, "<< name << "!\n";
}

#include "nbind/nbind.h"

NBIND_CLASS(Greeter) {
method(sayHello);
}

Does it make sense to bind a class here? Or how to I bind a class which was declared in the header file....

All the best.

Transferring a buffer

I have the following requirement: On the c++ side I create a buffer with a 32-bit rgba image data (not encoded).
On the js side I want to feed this data into a Uint8ClampedArray to be used in a canvas element.
currently I return the buffer from c++ as a std::vector<uint8_t>. On the javascript side I get a number[] which I then have to convert to the correct type.
These conversions are quite expensive so I was wondering if there was a way to fill a the Uint8ClampedArray directly on the c++ side? Or is this something that will be possible in the future?

This issue isn't really time critical for me, just want to know if I need to take a different approach.

"Light garbage collection" on Emscripten target

Together with supporting smart pointers, a simple GC could be added also on Emscripten target, enabled by calling bindings.enableLightGC(). C++ objects "owned" by JavaScript (created with JavaScript new operator or received through smart pointers) will be added to a list and freed automatically on the next tick, using setTimeout(..., 0);.

Pointers can be kept around for longer by calling their .persist() method, and later disposed by calling .free() same as currently. The default automatic freeing allows receiving temporary objects without having to worry about their lifetime.

Optional V8-style "handle scopes" could also be introduced. Any pointers received would then live as long as their scope. Scopes are opened upon creation and can be closed, re-opened and destroyed afterwards. Pointers are attached to the scope last opened. This would allow creating a bunch of temporary objects and later using and automatically freeing them from a callback or promise.

Todo:

  • Light GC
  • Handle scopes

Process crashes when passing object as callback argument

Process crashes with a segmentation fault if I pass an object of a custom class as argument in a callback.
I tried with classes byref and byval.

If I use a primitive value as argument the callback is called successfully and value is received on js side.

Process:               node [2547]
Path:                  /Users/USER/*/node
Identifier:            node
Version:               ???
Code Type:             X86-64 (Native)
Parent Process:        zsh [521]
Responsible:           iTerm2 [447]
User ID:               501

Date/Time:             2016-06-28 08:49:24.666 +0200
OS Version:            Mac OS X 10.10.5 (14F1808)
Report Version:        11
Anonymous UUID:        220DC629-9775-B751-A0F5-14B57937EEB0


Time Awake Since Boot: 670 seconds

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000

VM Regions Near 0:
--> 
    __TEXT                 000000010d163000-000000010e164000 [ 16.0M] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   ???                             0x00003214c7037f73 0 + 55064819629939
1   ???                             0x00003214c7022922 0 + 55064819542306
2   node                            0x000000010d58a42a v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, bool, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, v8::internal::Handle<v8::internal::Object>) + 410
3   node                            0x000000010d58a1b3 v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) + 467
4   node                            0x000000010d2ad706 v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 470
5   node                            0x000000010d92566d node::MakeCallback(node::Environment*, v8::Local<v8::Value>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*) + 718
6   node                            0x000000010d925c62 node::MakeCallback(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*) + 100
7   nbind.node                      0x000000010f03e7a9 Nan::Callback::Call_(v8::Isolate*, v8::Local<v8::Object>, int, v8::Local<v8::Value>*) const + 105 (v8.h:953)
8   nbind.node                      0x000000010f062ff6 MouseEvent(UiAreaHandler*, UiArea*, uiAreaMouseEvent*) + 166 (nan.h:1428)
9   libui.A.dylib                   0x000000010f30d870 -[areaView doMouseEvent:] + 1168
10  libui.A.dylib                   0x000000010f30d8be -[areaView mouseMoved:] + 62
11  com.apple.AppKit                0x00007fff90dc220a -[NSTrackingArea mouseMoved:] + 145
12  com.apple.AppKit                0x00007fff91398050 -[NSWindow _reallySendEvent:isDelayedEvent:] + 1185
13  com.apple.AppKit                0x00007fff90d2ac86 -[NSWindow sendEvent:] + 470
14  com.apple.AppKit                0x00007fff90d2761b -[NSApplication sendEvent:] + 3537
15  libui.A.dylib                   0x000000010f3282c4 -[applicationClass sendEvent:] + 84
16  libui.A.dylib                   0x000000010f328b43 uiMainStep + 291
17  nbind.node                      0x000000010f0f796c v8::Local<v8::Value> nbind::Caller<int, nbind::TypeList<nbind::ArgFromWire<0ul, int> > >::callFunction<int (*)(int), Nan::FunctionCallbackInfo<v8::Value> const>(int (*)(int), Nan::FunctionCallbackInfo<v8::Value> const&) + 44 (Caller.h:103)
18  nbind.node                      0x000000010f0f7774 void nbind::TemplatedBaseSignature<nbind::FunctionSignature<int (*)(int), Ui, int, int>, int, int>::callInnerSafely<void, Nan::FunctionCallbackInfo<v8::Value> const, Nan::FunctionCallbackInfo<v8::Value> const>(Nan::FunctionCallbackInfo<v8::Value> const&, Nan::FunctionCallbackInfo<v8::Value> const&) + 196 (v8.h:7574)
19  nbind.node                      0x000000010f03b253 Nan::imp::FunctionCallbackWrapper(v8::FunctionCallbackInfo<v8::Value> const&) + 131 (nan_callbacks_12_inl.h:175)
20  ???                             0x00003214c7175c08 0 + 55064820931592
21  ???                             0x00003214c7176284 0 + 55064820933252
22  ???                             0x00003214c717337a 0 + 55064820921210
23  ???                             0x00003214c7185a56 0 + 55064820996694
24  ???                             0x00003214c7037f84 0 + 55064819629956
25  ???                             0x00003214c7022922 0 + 55064819542306
26  node                            0x000000010d58a42a v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, bool, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, v8::internal::Handle<v8::internal::Object>) + 410
27  node                            0x000000010d58a1b3 v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) + 467
28  node                            0x000000010d2ad706 v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 470
29  node                            0x000000010d92566d node::MakeCallback(node::Environment*, v8::Local<v8::Value>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*) + 718
30  node                            0x000000010d92dbe6 node::CheckImmediate(uv_check_s*) + 98
31  node                            0x000000010da5fec5 uv__run_check + 167
32  node                            0x000000010da5b1e3 uv_run + 329
33  node                            0x000000010d92d9eb node::Start(int, char**) + 594
34  node                            0x000000010d163d34 start + 52

Thread 1:: V8 WorkerThread
0   libsystem_kernel.dylib          0x00007fff925b651a semaphore_wait_trap + 10
1   node                            0x000000010da6d677 v8::base::Semaphore::Wait() + 23
2   node                            0x000000010d98b029 v8::platform::TaskQueue::GetNext() + 57
3   node                            0x000000010d98b22b v8::platform::WorkerThread::Run() + 43
4   node                            0x000000010da6f377 v8::base::ThreadEntry(void*) + 87
5   libsystem_pthread.dylib         0x00007fff96b2c05a _pthread_body + 131
6   libsystem_pthread.dylib         0x00007fff96b2bfd7 _pthread_start + 176
7   libsystem_pthread.dylib         0x00007fff96b293ed thread_start + 13

Thread 2:: V8 WorkerThread
0   libsystem_kernel.dylib          0x00007fff925b651a semaphore_wait_trap + 10
1   node                            0x000000010da6d677 v8::base::Semaphore::Wait() + 23
2   node                            0x000000010d98b029 v8::platform::TaskQueue::GetNext() + 57
3   node                            0x000000010d98b22b v8::platform::WorkerThread::Run() + 43
4   node                            0x000000010da6f377 v8::base::ThreadEntry(void*) + 87
5   libsystem_pthread.dylib         0x00007fff96b2c05a _pthread_body + 131
6   libsystem_pthread.dylib         0x00007fff96b2bfd7 _pthread_start + 176
7   libsystem_pthread.dylib         0x00007fff96b293ed thread_start + 13

Thread 3:: V8 WorkerThread
0   libsystem_kernel.dylib          0x00007fff925b651a semaphore_wait_trap + 10
1   node                            0x000000010da6d677 v8::base::Semaphore::Wait() + 23
2   node                            0x000000010d98b029 v8::platform::TaskQueue::GetNext() + 57
3   node                            0x000000010d98b22b v8::platform::WorkerThread::Run() + 43
4   node                            0x000000010da6f377 v8::base::ThreadEntry(void*) + 87
5   libsystem_pthread.dylib         0x00007fff96b2c05a _pthread_body + 131
6   libsystem_pthread.dylib         0x00007fff96b2bfd7 _pthread_start + 176
7   libsystem_pthread.dylib         0x00007fff96b293ed thread_start + 13

Thread 4:: V8 WorkerThread
0   libsystem_kernel.dylib          0x00007fff925b651a semaphore_wait_trap + 10
1   node                            0x000000010da6d677 v8::base::Semaphore::Wait() + 23
2   node                            0x000000010d98b029 v8::platform::TaskQueue::GetNext() + 57
3   node                            0x000000010d98b22b v8::platform::WorkerThread::Run() + 43
4   node                            0x000000010da6f377 v8::base::ThreadEntry(void*) + 87
5   libsystem_pthread.dylib         0x00007fff96b2c05a _pthread_body + 131
6   libsystem_pthread.dylib         0x00007fff96b2bfd7 _pthread_start + 176
7   libsystem_pthread.dylib         0x00007fff96b293ed thread_start + 13

Thread 5:: Dispatch queue: com.apple.libdispatch-manager
0   libsystem_kernel.dylib          0x00007fff925bc232 kevent64 + 10
1   libdispatch.dylib               0x00007fff9402f26e _dispatch_mgr_thread + 52

Thread 6:
0   libsystem_kernel.dylib          0x00007fff925bb94a __workq_kernreturn + 10
1   libsystem_pthread.dylib         0x00007fff96b293dd start_wqthread + 13

Thread 7:
0   libsystem_kernel.dylib          0x00007fff925bb94a __workq_kernreturn + 10
1   libsystem_pthread.dylib         0x00007fff96b293dd start_wqthread + 13

Thread 8:
0   libsystem_kernel.dylib          0x00007fff925bb94a __workq_kernreturn + 10
1   libsystem_pthread.dylib         0x00007fff96b293dd start_wqthread + 13

Thread 9:
0   libsystem_kernel.dylib          0x00007fff925bb94a __workq_kernreturn + 10
1   libsystem_pthread.dylib         0x00007fff96b293dd start_wqthread + 13

Thread 10:
0   libsystem_kernel.dylib          0x00007fff925bb94a __workq_kernreturn + 10
1   libsystem_pthread.dylib         0x00007fff96b293dd start_wqthread + 13

Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000003  rbx: 0x00007fff52a9b760  rcx: 0x0000000000000002  rdx: 0x000009960c404189
  rdi: 0x0000008ab4911e09  rsi: 0x000009960c4ac679  rbp: 0x00007fff52a9b378  rsp: 0x00007fff52a9b340
   r8: 0x00007fff52a9b760   r9: 0x0000000000000003  r10: 0x0000000000000000  r11: 0x0000000000000018
  r12: 0x0000008ab4911e09  r13: 0x00007f99390000b8  r14: 0x00007f9939000000  r15: 0x00007f993903be90
  rip: 0x00003214c7037f73  rfl: 0x0000000000010297  cr2: 0x0000000000000000

Logical CPU:     2
Error Code:      0x00000004
Trap Number:     14


Binary Images:
       0x10d163000 -        0x10e1636b7 +node (???) <8C74A387-DBEE-315A-B0C6-C588C3661A63> /Users/USER/*/node
       0x10f02f000 -        0x10f14dfff +nbind.node (???) <6CD0C4E4-9094-3CC3-B0D8-025B0E53C620> /Users/USER/Desktop/*/nbind.node
       0x10f308000 -        0x10f33cfff +libui.A.dylib (0) <02989084-2EB9-3E3A-BD14-CFEFC9A2ED50> /Users/USER/Desktop/*/libui.A.dylib
    0x7fff68d9b000 -     0x7fff68dd192f  dyld (353.2.4) <708E385E-50C6-32A3-983C-42E97BEE4346> /usr/lib/dyld
    0x7fff8aaa4000 -     0x7fff8ac89ff7  libicucore.A.dylib (531.50) <CAA7ACE0-4012-3A13-864D-2B56B4B072FD> /usr/lib/libicucore.A.dylib
    0x7fff8ac8a000 -     0x7fff8acbafff  libsystem_m.dylib (3086.1) <1E12AB45-6D96-36D0-A226-F24D9FB0D9D6> /usr/lib/system/libsystem_m.dylib
    0x7fff8acbb000 -     0x7fff8ae6bff3  com.apple.QuartzCore (1.10 - 361.19) <E59000AA-DC30-3F73-A103-0240576C9556> /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore
    0x7fff8af04000 -     0x7fff8af9aff7  com.apple.cloudkit.CloudKit (283.67.4 - 283.67.4) <EA6E4B2C-A3AA-3636-B9C3-F61D3EFFB82B> /System/Library/Frameworks/CloudKit.framework/Versions/A/CloudKit
    0x7fff8af9b000 -     0x7fff8b0aaff3  com.apple.desktopservices (1.9.3 - 1.9.3) <FEE11342-5BC4-37A7-8169-DA48BE17B9C9> /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv
    0x7fff8b0b6000 -     0x7fff8b0b7ff7  libsystem_blocks.dylib (65) <9615D10A-FCA7-3BE4-AA1A-1B195DACE1A1> /usr/lib/system/libsystem_blocks.dylib
    0x7fff8b495000 -     0x7fff8b714ff7  com.apple.CoreData (111 - 526.3) <5A27E0D8-5E5A-335B-B3F6-2601C7B976FA> /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData
    0x7fff8b767000 -     0x7fff8b9ddfff  com.apple.security (7.0 - 57031.40.8) <FB238FFF-AA3B-3AB3-80F8-2DA8D2ADA15A> /System/Library/Frameworks/Security.framework/Versions/A/Security
    0x7fff8b9de000 -     0x7fff8b9defff  com.apple.Accelerate.vecLib (3.10 - vecLib 3.10) <B92888D0-ED3F-3430-8F3A-6E56FD16C5F1> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib
    0x7fff8bb12000 -     0x7fff8bf42fff  com.apple.vision.FaceCore (3.1.6 - 3.1.6) <C3B823AA-C261-37D3-B4AC-C59CE91C8241> /System/Library/PrivateFrameworks/FaceCore.framework/Versions/A/FaceCore
    0x7fff8bf43000 -     0x7fff8bf52fff  com.apple.LangAnalysis (1.7.0 - 1.7.0) <D1E527E4-C561-352F-9457-E8C50232793C> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
    0x7fff8bf53000 -     0x7fff8c360ff7  libLAPACK.dylib (1128) <F9201AE7-B031-36DB-BCF8-971E994EF7C1> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
    0x7fff8c54d000 -     0x7fff8c598ff7  com.apple.CloudDocs (1.0 - 321.10) <A8221290-A2A5-3767-BB26-CC57AC18D4DC> /System/Library/PrivateFrameworks/CloudDocs.framework/Versions/A/CloudDocs
    0x7fff8c599000 -     0x7fff8c60dffb  com.apple.securityfoundation (6.0 - 55126) <344401F5-4016-3AEB-BFDC-CE8E5546D39F> /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation
    0x7fff8c60e000 -     0x7fff8c910ffb  com.apple.GeoServices (1.0 - 1077.0.18) <2BBF8B44-DD46-3432-8C84-6D6AA004C233> /System/Library/PrivateFrameworks/GeoServices.framework/Versions/A/GeoServices
    0x7fff8c911000 -     0x7fff8c911fff  libOpenScriptingUtil.dylib (162.2) <D6A2216D-ADB2-3F24-AD30-F6D00829F545> /usr/lib/libOpenScriptingUtil.dylib
    0x7fff8c9ba000 -     0x7fff8c9c4ff7  com.apple.NetAuth (5.2 - 5.2) <2BBD749A-8E18-35B8-8E48-A90347C1CCA7> /System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth
    0x7fff8ca09000 -     0x7fff8ca17ff7  com.apple.opengl (11.1.6 - 11.1.6) <DB9F2798-F31F-335E-90A9-992C3AA7ECA8> /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL
    0x7fff8cb82000 -     0x7fff8cd10fff  libBLAS.dylib (1128) <497912C1-A98E-3281-BED7-E9C751552F61> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
    0x7fff8cd6c000 -     0x7fff8cdacff7  libGLImage.dylib (11.1.6) <D6DDC014-2C74-34B3-970A-26F211FF76EF> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib
    0x7fff8cdb9000 -     0x7fff8cdb9fff  com.apple.audio.units.AudioUnit (1.12 - 1.12) <E5335492-7EFE-31EA-BE72-4A9CEE68D58E> /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit
    0x7fff8dd95000 -     0x7fff8e0c8ff7  libmecabra.dylib (666.7) <0ED8AE5E-7A5B-34A6-A2EE-2B852E60E1E2> /usr/lib/libmecabra.dylib
    0x7fff8e0fb000 -     0x7fff8e106ff7  com.apple.CrashReporterSupport (10.10 - 631) <C44259AC-0A1C-3EC5-99AC-48CB520A709D> /System/Library/PrivateFrameworks/CrashReporterSupport.framework/Versions/A/CrashReporterSupport
    0x7fff8e11f000 -     0x7fff8e132ff7  com.apple.CoreBluetooth (1.0 - 1) <8D7BA9BA-EB36-307A-9119-0B3D9732C953> /System/Library/Frameworks/CoreBluetooth.framework/Versions/A/CoreBluetooth
    0x7fff8e17f000 -     0x7fff8e185ff7  libsystem_networkextension.dylib (167.40.3) <BA58B30B-8377-3B0A-8AE3-4F84021D9D4E> /usr/lib/system/libsystem_networkextension.dylib
    0x7fff8e187000 -     0x7fff8e18ffff  libsystem_platform.dylib (63) <64E34079-D712-3D66-9CE2-418624A5C040> /usr/lib/system/libsystem_platform.dylib
    0x7fff8e1c7000 -     0x7fff8e3d7ff7  com.apple.CFNetwork (720.5.7 - 720.5.7) <A47D7DD2-5903-39D0-8D27-5A7E2D119D84> /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork
    0x7fff8e3d8000 -     0x7fff8e515fff  com.apple.ImageIO.framework (3.3.0 - 1241) <BCBBC66A-5028-3BA5-8087-C9E7BBC3A65B> /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
    0x7fff8e516000 -     0x7fff8e57dff7  com.apple.framework.CoreWiFi (3.0 - 300.4) <19269C1D-EB29-384A-83F3-7DDDEB7D9DAD> /System/Library/PrivateFrameworks/CoreWiFi.framework/Versions/A/CoreWiFi
    0x7fff8e5b1000 -     0x7fff8e5d1ff7  com.apple.MultitouchSupport.framework (264.6 - 264.6) <1539F1F6-6334-37F3-9C52-02EFFBF4835D> /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport
    0x7fff8e6c1000 -     0x7fff8e7daffb  com.apple.CoreText (454.11 - 454.11) <7E5228C8-8657-3B6C-B3A4-98B79A3041EA> /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText
    0x7fff8ef50000 -     0x7fff8ef66ff7  libsystem_asl.dylib (267) <F153AC5B-0542-356E-88C8-20A62CA704E2> /usr/lib/system/libsystem_asl.dylib
    0x7fff8ef72000 -     0x7fff8efc3fff  com.apple.audio.CoreAudio (4.3.0 - 4.3.0) <8E6AE326-9F3E-3182-BD9E-FDF561211E2E> /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio
    0x7fff8efcc000 -     0x7fff8f045fe7  libcorecrypto.dylib (233.30.1) <5779FFA0-4D9A-3AD4-B7F2-618227621DC8> /usr/lib/system/libcorecrypto.dylib
    0x7fff8f06c000 -     0x7fff8f06fffb  libCGXType.A.dylib (788.3.3) <A8FBCF21-3266-37CE-BBFB-28A036ED83C6> /System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGXType.A.dylib
    0x7fff8f096000 -     0x7fff8f114fff  com.apple.CoreServices.OSServices (640.4 - 640.4) <9D175CD9-B27F-3529-8269-66D8AA83582E> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices
    0x7fff8f3cf000 -     0x7fff8f407fff  com.apple.RemoteViewServices (2.0 - 99) <C9A62691-B0D9-34B7-B71C-A48B5F4DC553> /System/Library/PrivateFrameworks/RemoteViewServices.framework/Versions/A/RemoteViewServices
    0x7fff8f9a6000 -     0x7fff8fba046f  libobjc.A.dylib (647) <759E155D-BC42-3D4E-869B-6F57D477177C> /usr/lib/libobjc.A.dylib
    0x7fff8fba4000 -     0x7fff8fbdeffb  com.apple.DebugSymbols (115 - 115) <6F03761D-7C3A-3C80-8031-AA1C1AD7C706> /System/Library/PrivateFrameworks/DebugSymbols.framework/Versions/A/DebugSymbols
    0x7fff8fbe8000 -     0x7fff8fbeafff  com.apple.loginsupport (1.0 - 1) <DAAD7013-A19D-3858-BFF7-DE1DAF664401> /System/Library/PrivateFrameworks/login.framework/Versions/A/Frameworks/loginsupport.framework/Versions/A/loginsupport
    0x7fff8fbeb000 -     0x7fff8fd2efff  libsqlite3.dylib (168.2) <BCB1F77E-2484-3EC4-A1D5-1AE90A407A23> /usr/lib/libsqlite3.dylib
    0x7fff8fd81000 -     0x7fff8fdb0ff7  com.apple.CoreServicesInternal (221.7.2 - 221.7.2) <B93D4775-149C-3698-B38C-9C50673D455C> /System/Library/PrivateFrameworks/CoreServicesInternal.framework/Versions/A/CoreServicesInternal
    0x7fff8fdfc000 -     0x7fff8fe9efff  com.apple.Bluetooth (4.3.6 - 4.3.6f3) <16970DB9-B0F4-3987-B751-C8702110E950> /System/Library/Frameworks/IOBluetooth.framework/Versions/A/IOBluetooth
    0x7fff902ed000 -     0x7fff90328fff  com.apple.QD (301 - 301) <C4D2AD03-B839-350A-AAF0-B4A08F8BED77> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD
    0x7fff90329000 -     0x7fff9032aff3  libSystem.B.dylib (1213) <2EB8A092-829F-3F63-B6F5-AF4FDB608476> /usr/lib/libSystem.B.dylib
    0x7fff906ec000 -     0x7fff906f5ff3  com.apple.CommonAuth (4.0 - 2.0) <9A484EE6-0003-3AB1-AE4F-AA543BBBF53F> /System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth
    0x7fff906f6000 -     0x7fff90713ffb  libresolv.9.dylib (57) <26B38E61-298A-3C3A-82C1-3B5E98AD5E29> /usr/lib/libresolv.9.dylib
    0x7fff90b98000 -     0x7fff90bc9ff7  com.apple.ProtectedCloudStorage (1.0 - 1) <9D76F2E0-C28A-3DBC-A91F-E87888D46BF0> /System/Library/PrivateFrameworks/ProtectedCloudStorage.framework/Versions/A/ProtectedCloudStorage
    0x7fff90bca000 -     0x7fff9174bff7  com.apple.AppKit (6.9 - 1348.17) <E485D56D-3E72-34B7-99BB-BFDEE2D07BF5> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
    0x7fff91992000 -     0x7fff919b2fff  com.apple.IconServices (47.1 - 47.1) <E83DFE3B-6541-3736-96BB-26DC5D0100F1> /System/Library/PrivateFrameworks/IconServices.framework/Versions/A/IconServices
    0x7fff91b1b000 -     0x7fff91c0dff7  libiconv.2.dylib (42) <2A06D02F-8B76-3864-8D96-64EF5B40BC6C> /usr/lib/libiconv.2.dylib
    0x7fff91c0e000 -     0x7fff91c68ff7  com.apple.LanguageModeling (1.0 - 1) <ACA93FE0-A0E3-333E-AE3C-8EB7DE5F362F> /System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling
    0x7fff91ccd000 -     0x7fff91d17fff  com.apple.HIServices (1.22 - 523) <99ADA325-53C8-368E-A5FA-3F913CD2245A> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices
    0x7fff91d89000 -     0x7fff91dd5fff  com.apple.corelocation (1486.17 - 1615.24) <8825B3E2-E053-3E01-AE31-793443962D06> /System/Library/Frameworks/CoreLocation.framework/Versions/A/CoreLocation
    0x7fff91dd6000 -     0x7fff91e2afff  libc++.1.dylib (120) <1B9530FD-989B-3174-BB1C-BDC159501710> /usr/lib/libc++.1.dylib
    0x7fff91e2b000 -     0x7fff91e50ff7  libJPEG.dylib (1241) <A6635296-BCC9-35E5-A5AF-351B039B5087> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib
    0x7fff91e65000 -     0x7fff91e69fff  libcache.dylib (69) <45E9A2E7-99C4-36B2-BEE3-0C4E11614AD1> /usr/lib/system/libcache.dylib
    0x7fff91e6a000 -     0x7fff91e6efff  libpam.2.dylib (20) <E805398D-9A92-31F8-8005-8DC188BD8B6E> /usr/lib/libpam.2.dylib
    0x7fff91e6f000 -     0x7fff92207ff7  com.apple.CoreFoundation (6.9 - 1153.18) <5C0892B8-9691-341F-9279-CA3A74D59AA0> /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
    0x7fff92208000 -     0x7fff92263ff7  libTIFF.dylib (1241) <4FADAE48-44A5-351D-A33F-211A9544E5A9> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib
    0x7fff922a6000 -     0x7fff922a7fff  libsystem_secinit.dylib (18) <581DAD0F-6B63-3A48-B63B-917AF799ABAA> /usr/lib/system/libsystem_secinit.dylib
    0x7fff922a8000 -     0x7fff922a8fff  com.apple.Accelerate (1.10 - Accelerate 1.10) <F1B96A61-7E4B-31BD-A35B-BA7EF1F16EF4> /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
    0x7fff922a9000 -     0x7fff922d9ff3  com.apple.GSS (4.0 - 2.0) <97F2A028-44CF-3188-B863-F4EEB39CBDBD> /System/Library/Frameworks/GSS.framework/Versions/A/GSS
    0x7fff922de000 -     0x7fff92373ff7  com.apple.ColorSync (4.9.0 - 4.9.0) <9150C2B7-2E6E-3509-96EA-7B3F959F049E> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync
    0x7fff9239d000 -     0x7fff923b8fff  com.apple.AppleVPAFramework (1.4.5 - 1.4.5) <B21714FD-3F2E-36D8-996E-EC74676F933F> /System/Library/PrivateFrameworks/AppleVPA.framework/Versions/A/AppleVPA
    0x7fff925a5000 -     0x7fff925c2fff  libsystem_kernel.dylib (2782.50.3) <64C4FFFD-8626-37C7-B480-414F52CF9ED2> /usr/lib/system/libsystem_kernel.dylib
    0x7fff925c3000 -     0x7fff925c5fff  libsystem_configuration.dylib (699.40.2) <56F94DCE-DBDE-3615-8F07-DE6270D9F8BE> /usr/lib/system/libsystem_configuration.dylib
    0x7fff92658000 -     0x7fff92674fff  com.apple.GenerationalStorage (2.0 - 209.11) <9FF8DD11-25FB-3047-A5BF-9415339B3EEC> /System/Library/PrivateFrameworks/GenerationalStorage.framework/Versions/A/GenerationalStorage
    0x7fff9267d000 -     0x7fff926a6ffb  libxslt.1.dylib (13.10) <E605CE87-3BC7-38ED-99A4-F218044B6B25> /usr/lib/libxslt.1.dylib
    0x7fff926a7000 -     0x7fff9279bff7  libFontParser.dylib (134.10) <6CF434A2-91CA-3477-BDE2-124508EDA05D> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib
    0x7fff9279c000 -     0x7fff927adfff  libcmph.dylib (1) <46EC3997-DB5E-38AE-BBBB-A035A54AD3C0> /usr/lib/libcmph.dylib
    0x7fff927fd000 -     0x7fff92838fff  com.apple.Symbolication (1.4 - 56045) <D64571B1-4483-3FE2-BD67-A91360F79727> /System/Library/PrivateFrameworks/Symbolication.framework/Versions/A/Symbolication
    0x7fff92839000 -     0x7fff9283dfff  libCoreVMClient.dylib (79.1) <201EF6DF-5074-3CB7-A361-398CF957A264> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib
    0x7fff9283e000 -     0x7fff92b43ff3  com.apple.HIToolbox (2.1.1 - 758.7) <B1188DED-5E71-3AB4-9E57-67F84C116ECE> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox
    0x7fff92b70000 -     0x7fff92bbfff7  libstdc++.6.dylib (104.1) <803F6AC8-87DC-3E24-9E80-729B551F6FFF> /usr/lib/libstdc++.6.dylib
    0x7fff92bc0000 -     0x7fff92cb2fff  libxml2.2.dylib (26.8) <77B9C30D-8907-3EE5-8854-DA11F546E457> /usr/lib/libxml2.2.dylib
    0x7fff92cbe000 -     0x7fff92cc0fff  libCVMSPluginSupport.dylib (11.1.6) <F82BF8C4-12D3-3EAD-AEDE-533AC08AEB4A> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib
    0x7fff92cfe000 -     0x7fff92cfeff7  libkeymgr.dylib (28) <77845842-DE70-3CC5-BD01-C3D14227CED5> /usr/lib/system/libkeymgr.dylib
    0x7fff92cff000 -     0x7fff92d06ff7  libCGCMS.A.dylib (788.3.3) <4E5F235E-DB39-3092-BB8E-71D25EA1D01A> /System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGCMS.A.dylib
    0x7fff92d07000 -     0x7fff92d12ff7  libkxld.dylib (2782.50.3) <D0801DA2-9A43-3CA6-81A0-C5AD85BB2191> /usr/lib/system/libkxld.dylib
    0x7fff92d1b000 -     0x7fff92db9fff  com.apple.Metadata (10.7.0 - 917.36) <00C4CB5D-E723-3612-84E0-439098392CDD> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata
    0x7fff92dba000 -     0x7fff92dc0fff  com.apple.speech.recognition.framework (5.0.9 - 5.0.9) <BB2D573F-0A01-379F-A2BA-3C454EDCB111> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition
    0x7fff92dc1000 -     0x7fff92dc6fff  com.apple.DiskArbitration (2.6 - 2.6) <0DFF4D9B-2AC3-3B82-B5C5-30F4EFBD2DB9> /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
    0x7fff92df7000 -     0x7fff92e11ff3  com.apple.Ubiquity (1.3 - 313) <DF56A657-CC6E-3BE2-86A0-71F07127724C> /System/Library/PrivateFrameworks/Ubiquity.framework/Versions/A/Ubiquity
    0x7fff92e15000 -     0x7fff92e17fff  libsystem_sandbox.dylib (358.20.5) <3F5E973F-C702-31AC-97BC-05F5C195683C> /usr/lib/system/libsystem_sandbox.dylib
    0x7fff92e18000 -     0x7fff92e50fff  libsystem_network.dylib (412.20.3) <6105C134-6722-3C0A-A4CE-5E1261E2E1CC> /usr/lib/system/libsystem_network.dylib
    0x7fff930ab000 -     0x7fff930faff7  com.apple.opencl (2.4.2 - 2.4.2) <D1223A7D-419F-36E9-9BDF-55C03167C6CA> /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL
    0x7fff930fb000 -     0x7fff93103ff3  com.apple.CoreServices.FSEvents (1210.20.1 - 1210.20.1) <84F79D3E-7B5E-3C93-8479-35794A3F125E> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents
    0x7fff93107000 -     0x7fff931faff7  libJP2.dylib (1241) <E3D08E10-9E4E-3C19-B107-233A567B20D8> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib
    0x7fff93216000 -     0x7fff934fdffb  com.apple.CoreServices.CarbonCore (1108.6 - 1108.6) <8953580E-7857-33B2-AA64-98296830D3A8> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
    0x7fff93516000 -     0x7fff93563ff7  com.apple.print.framework.PrintCore (10.3 - 451.1) <DE992474-0841-38A1-B4F6-46D653E454D5> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore
    0x7fff9366b000 -     0x7fff9367cff7  libz.1.dylib (55) <88C7C7DE-04B8-316F-8B74-ACD9F3DE1AA1> /usr/lib/libz.1.dylib
    0x7fff938e8000 -     0x7fff93c19fff  com.apple.Foundation (6.9 - 1154) <49EE64E1-9F53-35D1-A481-2EFE2789B254> /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
    0x7fff93c1a000 -     0x7fff93d3eff7  com.apple.LaunchServices (644.56 - 644.56) <20AABB1C-9319-3E4D-A024-51B0DD5FCD3B> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices
    0x7fff93d3f000 -     0x7fff93db7ff7  com.apple.SystemConfiguration (1.14.4 - 1.14) <3DFFD7F7-BD23-3F4C-A209-C4A0D99F6573> /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
    0x7fff93db8000 -     0x7fff93dc9ff3  libsystem_coretls.dylib (35.40.1) <155DA0A9-2046-332E-BFA3-D7974A51F731> /usr/lib/system/libsystem_coretls.dylib
    0x7fff93dca000 -     0x7fff93e38ff3  com.apple.Heimdal (4.0 - 2.0) <8D1667CF-D454-3E07-A58E-E15591B5A95E> /System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal
    0x7fff93e39000 -     0x7fff93e4bff7  com.apple.CoreDuetDaemonProtocol (1.0 - 1) <CE9FABB4-1C5D-3F9B-9BB8-5CC50C3E5E31> /System/Library/PrivateFrameworks/CoreDuetDaemonProtocol.framework/Versions/A/CoreDuetDaemonProtocol
    0x7fff93e4c000 -     0x7fff93e92ff7  libauto.dylib (186) <A260789B-D4D8-316A-9490-254767B8A5F1> /usr/lib/libauto.dylib
    0x7fff93e93000 -     0x7fff93ea3ff7  libbsm.0.dylib (34) <A3A2E56C-2B65-37C7-B43A-A1F926E1A0BB> /usr/lib/libbsm.0.dylib
    0x7fff93ed1000 -     0x7fff93eebff7  com.apple.Kerberos (3.0 - 1) <7760E0C2-A222-3709-B2A6-B692D900CEB1> /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos
    0x7fff93eec000 -     0x7fff93f06ff7  libextension.dylib (55.2) <3BB019CA-199A-36AC-AA22-14B562138545> /usr/lib/libextension.dylib
    0x7fff93f07000 -     0x7fff93f14fff  libxar.1.dylib (255) <7CD69BB5-97BA-3858-8A8B-2F33F129E6E7> /usr/lib/libxar.1.dylib
    0x7fff93f61000 -     0x7fff93f7bff7  liblzma.5.dylib (7) <1D03E875-A7C0-3028-814C-3C27F7B7C079> /usr/lib/liblzma.5.dylib
    0x7fff93f7c000 -     0x7fff93f7ffff  com.apple.IOSurface (97.4 - 97.4) <AE11CFBC-4D46-30F3-BEEC-4C8131079391> /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface
    0x7fff93f93000 -     0x7fff93ffffff  com.apple.framework.CoreWLAN (5.0 - 500.35.2) <03697149-1CDD-32FF-B564-1C1EF5E9E5C3> /System/Library/Frameworks/CoreWLAN.framework/Versions/A/CoreWLAN
    0x7fff94000000 -     0x7fff94028fff  libsystem_info.dylib (459.40.1) <2E16C4B3-A327-3957-9C41-143911979A1E> /usr/lib/system/libsystem_info.dylib
    0x7fff94029000 -     0x7fff94053ff7  libdispatch.dylib (442.50.1) <A61E703C-784A-3698-B513-75DD12AAD6DC> /usr/lib/system/libdispatch.dylib
    0x7fff94054000 -     0x7fff94057ff7  libdyld.dylib (353.2.4) <224F35C5-6E35-3EC4-A97C-80949CE444E7> /usr/lib/system/libdyld.dylib
    0x7fff9417b000 -     0x7fff941a3fff  libxpc.dylib (559.40.1) <5C829202-962E-3744-8B50-00D38CC88E84> /usr/lib/system/libxpc.dylib
    0x7fff94233000 -     0x7fff942bcff7  com.apple.CoreSymbolication (3.1 - 57020.2) <FDAF88F6-7D11-37BC-B758-4B835FA657BA> /System/Library/PrivateFrameworks/CoreSymbolication.framework/Versions/A/CoreSymbolication
    0x7fff943be000 -     0x7fff9444afff  libsystem_c.dylib (1044.40.2) <69158EFA-8270-30A1-BA02-4F74A4498147> /usr/lib/system/libsystem_c.dylib
    0x7fff9444b000 -     0x7fff94466ff7  libCRFSuite.dylib (34) <D64842BE-7BD4-3D0C-9842-1D202F7C2A51> /usr/lib/libCRFSuite.dylib
    0x7fff944d2000 -     0x7fff944f8fff  com.apple.ChunkingLibrary (2.1 - 163.6) <29D4CB95-42EF-34C6-8182-BDB6F7BB1E79> /System/Library/PrivateFrameworks/ChunkingLibrary.framework/Versions/A/ChunkingLibrary
    0x7fff94537000 -     0x7fff945faff7  libvMisc.dylib (516) <21497A28-8DCB-3EB8-BDAC-93C93382B0AA> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib
    0x7fff945fb000 -     0x7fff94600fff  libsystem_stats.dylib (163.30.2) <6CD42621-C376-3E97-ACDE-0B98D5F961EA> /usr/lib/system/libsystem_stats.dylib
    0x7fff94821000 -     0x7fff94826ffb  libheimdal-asn1.dylib (398.40.1) <7D2BE3DE-60F7-3A6E-A92E-DA0EF9D3417E> /usr/lib/libheimdal-asn1.dylib
    0x7fff94827000 -     0x7fff94846fff  com.apple.CoreDuet (1.0 - 1) <36AA9FD5-2685-314D-B364-3FA4688D86BD> /System/Library/PrivateFrameworks/CoreDuet.framework/Versions/A/CoreDuet
    0x7fff94847000 -     0x7fff9484cff7  libmacho.dylib (862) <126CA2ED-DE91-308F-8881-B9DAEC3C63B6> /usr/lib/system/libmacho.dylib
    0x7fff948ae000 -     0x7fff94915ffb  com.apple.datadetectorscore (6.0 - 396.1.2) <E5A147AE-66B5-3D31-A2E0-D3FAB8417E1F> /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/DataDetectorsCore
    0x7fff94997000 -     0x7fff94997fff  com.apple.ApplicationServices (48 - 48) <5BF7910B-C328-3BF8-BA4F-CE52B574CE01> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices
    0x7fff94b13000 -     0x7fff94c2afe7  libvDSP.dylib (516) <DFEDB210-49D1-3803-88A2-C61DB6A45C3D> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib
    0x7fff94c2b000 -     0x7fff94c2cfff  libDiagnosticMessagesClient.dylib (100) <2EE8E436-5CDC-34C5-9959-5BA218D507FB> /usr/lib/libDiagnosticMessagesClient.dylib
    0x7fff94c36000 -     0x7fff94cbafff  com.apple.PerformanceAnalysis (1.0 - 1) <4E934EE0-5CC6-3D54-8FA2-5B8AE669D775> /System/Library/PrivateFrameworks/PerformanceAnalysis.framework/Versions/A/PerformanceAnalysis
    0x7fff94cbb000 -     0x7fff94ce6ff7  com.apple.DictionaryServices (1.2 - 229.1) <62EC3E1B-5A28-3252-90FF-C2E9999C2A2A> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices
    0x7fff94ce7000 -     0x7fff94d0cff7  libPng.dylib (1241) <E4244E6E-60F4-3478-BD18-1DD52E42EFD9> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib
    0x7fff94d45000 -     0x7fff94de4e27  com.apple.AppleJPEG (1.0 - 1) <6627DDD9-A8FE-3968-B23A-B6A29AA3919A> /System/Library/PrivateFrameworks/AppleJPEG.framework/Versions/A/AppleJPEG
    0x7fff94e58000 -     0x7fff94e65ff7  libbz2.1.0.dylib (36) <2DF83FBC-5C08-39E1-94F5-C28653791B5F> /usr/lib/libbz2.1.0.dylib
    0x7fff94e76000 -     0x7fff94e76ff7  libunc.dylib (29) <5676F7EA-C1DF-329F-B006-D2C3022B7D70> /usr/lib/system/libunc.dylib
    0x7fff957be000 -     0x7fff96021ff3  com.apple.CoreGraphics (1.600.0 - 788.3.3) <E2A852A3-F7DA-3D2A-B990-C11540CC6440> /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics
    0x7fff96154000 -     0x7fff96175fff  com.apple.framework.Apple80211 (10.3 - 1030.71.6) <C0A17391-5C8B-34B1-BD46-8D644AB57DE0> /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Apple80211
    0x7fff9634e000 -     0x7fff9647efff  com.apple.UIFoundation (1.0 - 1) <466BDFA8-0B9F-3AB0-989D-F9779422926A> /System/Library/PrivateFrameworks/UIFoundation.framework/Versions/A/UIFoundation
    0x7fff96970000 -     0x7fff9697bfff  libGL.dylib (11.1.6) <38B3FF9A-5660-3080-9DB8-1CAE0E8CD739> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
    0x7fff969bb000 -     0x7fff96a27ff3  com.apple.MMCS (1.3 - 327.5) <FC998246-ED60-334D-9E94-453F35EF9C78> /System/Library/PrivateFrameworks/MMCS.framework/Versions/A/MMCS
    0x7fff96a28000 -     0x7fff96a35ff3  com.apple.ProtocolBuffer (1 - 228.0.1) <3429EB06-9F0E-355F-B9AB-F72879177398> /System/Library/PrivateFrameworks/ProtocolBuffer.framework/Versions/A/ProtocolBuffer
    0x7fff96a93000 -     0x7fff96b27fff  com.apple.ink.framework (10.9 - 213) <8E029630-1530-3734-A446-13353F0E7AC5> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink
    0x7fff96b28000 -     0x7fff96b31fff  libsystem_pthread.dylib (105.40.1) <ACE90967-ECD0-3251-AEEB-461E3C6414F7> /usr/lib/system/libsystem_pthread.dylib
    0x7fff96cf4000 -     0x7fff96cf4ff7  liblaunch.dylib (559.40.1) <4F81CA3A-D2CE-3030-A89D-42F3DAD7BA8F> /usr/lib/system/liblaunch.dylib
    0x7fff96cf8000 -     0x7fff96d14ff7  libsystem_malloc.dylib (53.30.1) <DDA8928B-CC0D-3255-BD8A-3FEA0982B890> /usr/lib/system/libsystem_malloc.dylib
    0x7fff96e65000 -     0x7fff96e67ff7  libsystem_coreservices.dylib (9) <41B7C578-5A53-31C8-A96F-C73E030B0938> /usr/lib/system/libsystem_coreservices.dylib
    0x7fff96e90000 -     0x7fff96e97ff7  libcompiler_rt.dylib (35) <BF8FC133-EE10-3DA6-9B90-92039E28678F> /usr/lib/system/libcompiler_rt.dylib
    0x7fff96ebe000 -     0x7fff96ec0fff  com.apple.CoreDuetDebugLogging (1.0 - 1) <9A6E5710-EA99-366E-BF40-9A65EC1B46A1> /System/Library/PrivateFrameworks/CoreDuetDebugLogging.framework/Versions/A/CoreDuetDebugLogging
    0x7fff96ec1000 -     0x7fff97028ffb  com.apple.audio.toolbox.AudioToolbox (1.12 - 1.12) <5678FC94-456A-3F5F-BA9A-10EB6E462997> /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox
    0x7fff970ab000 -     0x7fff970acffb  libremovefile.dylib (35) <3485B5F4-6CE8-3C62-8DFD-8736ED6E8531> /usr/lib/system/libremovefile.dylib
    0x7fff97112000 -     0x7fff97114fff  libquarantine.dylib (76.20.1) <7AF90041-2768-378A-925A-D83161863642> /usr/lib/system/libquarantine.dylib
    0x7fff97491000 -     0x7fff9749dff7  com.apple.OpenDirectory (10.10 - 187) <22FF4721-03D8-381B-AA83-2B07D690C777> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory
    0x7fff9749e000 -     0x7fff974a9fff  libcommonCrypto.dylib (60061.30.1) <E789748D-F9A7-3CFF-B317-90DF348B1E95> /usr/lib/system/libcommonCrypto.dylib
    0x7fff974aa000 -     0x7fff974adfff  com.apple.xpc.ServiceManagement (1.0 - 1) <A95A15CD-3B21-3513-AFF8-1D7DE3DBFA12> /System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
    0x7fff974ae000 -     0x7fff97901fc7  com.apple.vImage (8.0 - 8.0) <33BE7B31-72DB-3364-B37E-C322A32748C5> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage
    0x7fff979f0000 -     0x7fff97a4ffff  com.apple.AE (681.5 - 681.7) <2BF39455-1CDD-392C-824A-9972C6B1FB57> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE
    0x7fff97a50000 -     0x7fff97a55ff7  libunwind.dylib (35.3) <BE7E51A0-B6EA-3A54-9CCA-9D88F683A6D6> /usr/lib/system/libunwind.dylib
    0x7fff97b71000 -     0x7fff97b95ff7  com.apple.Sharing (328.17 - 328.17) <AD5E243A-B79F-3D7B-800B-A2C99A1CFEF1> /System/Library/PrivateFrameworks/Sharing.framework/Versions/A/Sharing
    0x7fff97b96000 -     0x7fff97b96fff  com.apple.CoreServices (62 - 62) <C69DA8A7-B536-34BF-A93F-1C170E2C6D58> /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
    0x7fff97b97000 -     0x7fff97bc2fff  libc++abi.dylib (125) <88A22A0F-87C6-3002-BFBA-AC0F2808B8B9> /usr/lib/libc++abi.dylib
    0x7fff97caa000 -     0x7fff97cb2fff  libsystem_dnssd.dylib (576.50.2) <9EC5AF92-D0D2-3BDE-92B6-D3730D3865C8> /usr/lib/system/libsystem_dnssd.dylib
    0x7fff97cb3000 -     0x7fff97cdbfff  libRIP.A.dylib (788.3.3) <AAE534EA-35E7-3A67-80DA-765519E8A9BA> /System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib
    0x7fff97cdc000 -     0x7fff97ce3fff  com.apple.NetFS (6.0 - 4.0) <C263C8F8-F284-3101-AC82-A97A81716063> /System/Library/Frameworks/NetFS.framework/Versions/A/NetFS
    0x7fff98757000 -     0x7fff98763fff  com.apple.speech.synthesis.framework (5.3.11 - 5.3.11) <DFC7FD85-F1B0-317C-8513-722570CB8FB9> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis
    0x7fff98764000 -     0x7fff987aaff7  libFontRegistry.dylib (134.1) <CE41D8C2-BEED-345C-BC4F-3775CC06C672> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib
    0x7fff98b43000 -     0x7fff98b45fff  libRadiance.dylib (1241) <480E8A72-F5F9-31A4-BF63-28BAF3BB1F8E> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib
    0x7fff98b46000 -     0x7fff98b4effb  libcopyfile.dylib (118.1.2) <0C68D3A6-ACDD-3EF3-991A-CC82C32AB836> /usr/lib/system/libcopyfile.dylib
    0x7fff98b53000 -     0x7fff98bc2fff  com.apple.SearchKit (1.4.0 - 1.4.0) <80883BD1-C9BA-3794-A20E-476F94DD89A9> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit
    0x7fff98bc3000 -     0x7fff98c34ffb  com.apple.ApplicationServices.ATS (360 - 375.4) <888FE0B1-835C-30B1-80AD-5066CADB0364> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS
    0x7fff98d4a000 -     0x7fff98d77fff  com.apple.CoreVideo (1.8 - 145.1) <18DB07E0-B927-3260-A234-636F298D1917> /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo
    0x7fff98d78000 -     0x7fff98d85ff7  com.apple.SpeechRecognitionCore (2.1.2 - 2.1.2) <551322E2-C1E4-3378-A218-F362985E3E3C> /System/Library/PrivateFrameworks/SpeechRecognitionCore.framework/Versions/A/SpeechRecognitionCore
    0x7fff98da0000 -     0x7fff98e12fff  com.apple.framework.IOKit (2.0.2 - 1050.20.2) <09C0518C-90DF-3FC3-96D6-34D35F72C8EF> /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
    0x7fff98e51000 -     0x7fff98f11ff7  com.apple.backup.framework (1.6.5 - 1.6.5) <86396038-33EA-3046-9F70-093A3D6407D4> /System/Library/PrivateFrameworks/Backup.framework/Versions/A/Backup
    0x7fff98f2b000 -     0x7fff98f34fff  libGFXShared.dylib (11.1.6) <CB24B5DA-CB17-3A0B-94E1-5A58DADC3FBD> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib
    0x7fff98f35000 -     0x7fff98f3bfff  libsystem_trace.dylib (72.20.1) <840F5301-B55A-3078-90B9-FEFFD6CD741A> /usr/lib/system/libsystem_trace.dylib
    0x7fff98f3e000 -     0x7fff9920dff3  com.apple.CoreImage (10.3.5) <0224F5A6-636A-374B-B46C-13E066596725> /System/Library/Frameworks/QuartzCore.framework/Versions/A/Frameworks/CoreImage.framework/Versions/A/CoreImage
    0x7fff9920e000 -     0x7fff9924ffff  libGLU.dylib (11.1.6) <4BC6579D-A6D0-3A19-880E-E29FAEA698E7> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib
    0x7fff9927b000 -     0x7fff993a3ff7  com.apple.coreui (2.1 - 308.6) <9E0E9C6A-68F5-34C1-A17C-96226D401D4D> /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI
    0x7fff9941e000 -     0x7fff9946aff7  libcups.2.dylib (408.2) <E8AD18F9-61E4-3791-B840-504468C25556> /usr/lib/libcups.2.dylib
    0x7fff9946b000 -     0x7fff99482ff7  libLinearAlgebra.dylib (1128) <E78CCBAA-A999-3B65-8EC9-06DB15E67C37> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib
    0x7fff99483000 -     0x7fff9949cff7  com.apple.CFOpenDirectory (10.10 - 187) <F1805A0F-D5CC-35A8-9349-042D58D128B0> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory
    0x7fff9949d000 -     0x7fff994a6ff7  libsystem_notify.dylib (133.1.1) <61147800-F320-3DAA-850C-BADF33855F29> /usr/lib/system/libsystem_notify.dylib
    0x7fff99563000 -     0x7fff99567fff  com.apple.TCC (1.0 - 1) <CCA42EE2-3400-3444-9486-BC454E60D944> /System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC
    0x7fff99894000 -     0x7fff99895fff  liblangid.dylib (117) <B54A4AA0-2E53-3671-90F5-AFF711C0EB9E> /usr/lib/liblangid.dylib
    0x7fff99905000 -     0x7fff99909ff7  libGIF.dylib (1241) <8A3CB11A-5CB9-3008-A0E1-F8B56125F484> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib
    0x7fff9a19c000 -     0x7fff9a1c7ffb  libarchive.2.dylib (30.50.1) <C140763F-5470-3302-B3E0-651B4B5930ED> /usr/lib/libarchive.2.dylib

External Modification Summary:
  Calls made by other processes targeting this process:
    task_for_pid: 2
    thread_create: 0
    thread_set_state: 0
  Calls made by this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by all processes on this machine:
    task_for_pid: 683
    thread_create: 0
    thread_set_state: 0

VM Region Summary:
ReadOnly portion of Libraries: Total=207.6M resident=128.5M(62%) swapped_out_or_unallocated=79.2M(38%)
Writable regions: Total=90.4M written=14.2M(16%) resident=19.9M(22%) swapped_out=0K(0%) unallocated=70.5M(78%)

REGION TYPE                      VIRTUAL
===========                      =======
CG backing stores                  1256K
CG image                             16K
CG shared images                    176K
CoreAnimation                        20K
CoreUI image data                    56K
Dispatch continuations             8192K
Foundation                            4K
Kernel Alloc Once                     8K
MALLOC                             38.9M
MALLOC (admin)                       32K
Memory Tag 242                       12K
Memory Tag 255                    554.1M
Memory Tag 255 (reserved)           256K        reserved VM address space (unallocated)
STACK GUARD                        56.0M
Stack                              12.6M
VM_ALLOCATE                        17.1M
__DATA                             15.7M
__IMAGE                             528K
__LINKEDIT                         82.3M
__TEXT                            125.4M
__UNICODE                           552K
mapped file                        74.8M
shared memory                         4K
===========                      =======
TOTAL                             987.8M
TOTAL, minus reserved VM space    987.6M

Model: iMac11,2, BootROM IM112.0057.B03, 2 processors, Intel Core i3, 3.06 GHz, 4 GB, SMC 1.64f5
Graphics: ATI Radeon HD 4670, ATI Radeon HD 4670, PCIe, 256 MB
Memory Module: BANK 0/DIMM1, 2 GB, DDR3, 1333 MHz, 0x80CE, 0x4D34373142353637334648302D4348392020
Memory Module: BANK 1/DIMM1, 2 GB, DDR3, 1333 MHz, 0x80CE, 0x4D34373142353637334648302D4348392020
AirPort: spairport_wireless_card_type_airport_extreme (0x168C, 0x8F), Atheros 9280: 4.0.74.0-P2P
Bluetooth: Version 4.3.6f3 16238, 3 services, 27 devices, 1 incoming serial ports
Network Service: Ethernet, Ethernet, en0
Serial ATA Device: ST3500418AS, 500,11 GB
Serial ATA Device: HL-DT-STDVDRW  GA32N
USB Device: Hub
USB Device: BRCM2046 Hub
USB Device: Bluetooth USB Host Controller
USB Device: Internal Memory Card Reader
USB Device: Hub
USB Device: PS/2+USB Mouse
USB Device: Built-in iSight
USB Device: IR Receiver
Thunderbolt Bus: 

Minor resolve issue

Upon using $ npm install charto/nbind#<branch>, although the main field is specified in node_modules/nbind/package.json as dist/nbind.js, the module cannot be loaded with require('nbind'), since dist folder isn't included in the repo.

Compiling w/ C++14 or higher

Because nbind.gypi contains a bunch of various flags (such as -std=c++11), setting our own flags is actually a bit painful: one has to create another gypi file, include it after auto.gypi, and add a truthy condition inside (such as 1==1).

Is it really nbind's task to set the standard and optimization flags ? Shouldn't setting these flags be left to the user ? Or at least hidden behind a node-gyp variable ?

`nbind` fails to throw an Exception for wrong parameter type

I actually expect this test to pass:

test('newWindow - throw if width is not a number', t => {
    const err = t.throws(() => new libui.UiWindow('Test window', 'some text', 600, true));
    t.true(err instanceof Error);
});

because UiWindow constructor expects an int as second argument, but the code is not hrowing any error

using nbind / node-gyp with lot's of extra libraries - how to tell node-gyp where all sources are?

Take a C++ framework, e.g. https://github.com/vgteam/vg/tree/master/src having lots of dependencies when building.
Now I would like to e.g. nbind all classes in file https://github.com/vgteam/vg/tree/master/src/vg.cpp. The problem is that when executing
"npm run -- node-gyp configure build" the following happens:

../src/vg.hpp:11:10: fatal error: 'omp.h' file not found
#include <omp.h>
^
1 error generated.

This error does not occur if I build the project as specified in the wiki. Following this issue http://stackoverflow.com/questions/25990296/how-to-include-omp-h-in-os-x I have to state that gcc 4.9.3 via homebrew is installed and globally available. Maybe node-gyp does not use gcc / g++?
Is there anyway to pass all the source files necessary for the build to node-gyp or how do I proceed here? (I have a CMakeLists.txt file containing over 3000 lines of sources, can I pass this to node-gyp? Or would node-gyp be able to do this automatically?)

All the best.

Maybe feature request : implement "pass by proxy" classes

I started implementation of libui uiArea APIs.
An uiArea expected an uiAreaHandler struct holding pointers to functions that will handle drawing on the area itself:

struct uiAreaHandler {
    void (*Draw)(uiAreaHandler *, uiArea *, uiAreaDrawParams *);
    void (*MouseEvent)(uiAreaHandler *, uiArea *, uiAreaMouseEvent *);
    void (*MouseCrossed)(uiAreaHandler *, uiArea *, int left);
    void (*DragBroken)(uiAreaHandler *, uiArea *);
    int (*KeyEvent)(uiAreaHandler *, uiArea *, uiAreaKeyEvent *);
};

The uiArea widget invoke these functions when it need to redraw the area.
I cannot use class by reference here, because they need to be implemented in js by caller. And neither class by value, because functions will be executed on the native side with them...

So I and up building a struct that hold the needed pointers, and a subsequent set of nbind::cbFunction, one for each function pointer.

typedef struct UiAreaHandler {
    void (*Draw)(UiAreaHandler *self, UiArea *area, UiAreaDrawParams *params);
    void (*MouseEvent)(UiAreaHandler *self, UiArea *area, UiAreaMouseEvent *event);
    void (*MouseCrossed)(UiAreaHandler *self, UiArea *area, int left);
    void (*DragBroken)(UiAreaHandler *self, UiArea *area);
    int (*KeyEvent)(UiAreaHandler *self, UiArea *area, UiAreaKeyEvent *event);

    nbind::cbFunction *draw;
    nbind::cbFunction *mouseEvent;
    nbind::cbFunction *mouseCrossed;
    nbind::cbFunction *dragBroken;
    nbind::cbFunction *keyEvent;
} UiAreaHandler;

Then, I created a set of functions that call the js callbacks, and set their addresses on the struct, e.g.:

void Draw (UiAreaHandler *self, UiArea *area, UiAreaDrawParams *params) {
    (*(self->draw))();
}

And a factory function that is called from javascript with a set of js functions as arguments:

UiAreaHandler * UiAreaHandlerFactory::build(
    nbind::cbFunction &drawCb,
    nbind::cbFunction &mouseEventCb ,
    nbind::cbFunction &mouseCrossedCb,
    nbind::cbFunction &dragBrokenCb,
    nbind::cbFunction &keyEventCb
) {
    UiAreaHandler *handler = new UiAreaHandler();

    handler->draw = new nbind::cbFunction(drawCb);
    handler->mouseEvent = new nbind::cbFunction(mouseEventCb);
    handler->mouseCrossed = new nbind::cbFunction(mouseCrossedCb);
    handler->dragBroken = new nbind::cbFunction(dragBrokenCb);
    handler->keyEvent = new nbind::cbFunction(keyEventCb);

    handler->Draw = Draw;
    handler->MouseEvent = MouseEvent;
    handler->MouseCrossed = MouseCrossed;
    handler->DragBroken = DragBroken;
    handler->KeyEvent = KeyEvent;

    return handler;
}

So, I get a struct shaped like libui wants, and every time it call one of the functions in the struct, I call the corresponding js callback.

The APIs are not completed yet, but the method seems to work well...

  1. Do you see a way to simplify this stuff?
  2. Do you think this kind of use case could be automated by nbind in a future release?

Support React Native

An Objective C bridge (and later Java, when React Native supports Android) is needed to communicate between C++ and React Native, or a similar technology such as NativeScript or Cordova. This would allow writing heavy duty algorithms in C++ while still using JavaScript for the UI. This is important especially on iOS where the JavaScript engine available to apps doesn't support JIT. The tasks are:

  • Set up the project with an Objective C or Swift environment using React Native.
  • C++ to Objective C bridge, using jxcore-cordova as a reference.
  • JavaScript to Objective C bridge.
  • Bind the two handling static method calls and...
  • Numeric argument and return types
  • Pointers wrapped as objects
  • Constructors
  • Destructors
  • Non-static methods
  • String argument and return types
  • Getters and setters
  • Callbacks
  • Value types
  • Vectors

Persistent callbacks macros

I have been having trouble implementing asynchronous callbacks. After checking out past issues, such as #15 and #23, I am still not confident enough.

After studying libui-node's source, I found out that it now uses preprocessor definitions for DEFINE_EVENT and IMPLEMENT_EVENT.

Are there any plans for nbind to have such an abstraction? Or maybe get a minimal working example in the examples as a solid reference?

Support complex data structures

Something like emscripten::val could replace nbind::cbFunction and besides calling functions could allow also accessing objects and arrays by numeric or string keys.

In some cases it might be useful to pass a JSON object using something like nlohmann/json (or miloyip/nativejson-benchmark has a list of other library options) and avoid roundtrips between C++ and JavaScript at every access.

Support std::function

JavaScript callbacks could perhaps be converted automatically when the C++ parameter type is something like std::function<void(Node*)> lambda.

Plain function pointers probably won't work because we need state to hold a reference to the received JavaScript function.

return(foo) vs. return foo

Although most C/C++ veterans are pretty adamant about not using parenthesis in return statements historically this is just a matter of style and thus personal preference. However, C++14 will add semantics to these parenthesis in some cases.

Just a heads up, though...

CheckWire::check in Caller.h conflict with macOS macro defined in AssertMacros.h

This give me following error when compiling:

Expected member name or ';' after declaration specifiers.

Followed by mahy other errors (someway related to the same cause)

I found this answer on SO:

http://stackoverflow.com/questions/31665095/xcode-error-compiling-c-expected-member-name-or-after-declaration-specifie

I'm effectively able to successfully compile by inserting #undef check at the beginning of Caller.h, but I'm not sure this is free of consequences, if you use the macro in some other file...

nbind::cbFunction & works, but not nbind::cbFunction const &

As the title says, it seems something bad happens when passing a const ref as parameter of a function. I get the following error:

Error: Unbound type const 4419? & in TextLayout.setCharacterGetter
    at reportProblem (/home/arcanis/text-formatter/build/Release/nbind.js:1:36937)
    at getComplexType (/home/arcanis/text-formatter/build/Release/nbind.js:1:37591)
    at getComplexType (/home/arcanis/text-formatter/build/Release/nbind.js:1:37688)
    at Object.getComplexType (/home/arcanis/text-formatter/build/Release/nbind.js:1:37688)
    at /home/arcanis/text-formatter/build/Release/nbind.js:1:69302
    at Array.map (native)
    at Object.getTypes (/home/arcanis/text-formatter/build/Release/nbind.js:1:69250)
    at Object.makeMethodCaller (/home/arcanis/text-formatter/build/Release/nbind.js:1:89372)
    at BindClass.registerMethods (/home/arcanis/text-formatter/build/Release/nbind.js:1:76888)
    at BindClass.registerSuperMethods (/home/arcanis/text-formatter/build/Release/nbind.js:1:77416)

Default parameters become mandatory

I hope you won't mind me opening a shitload of issues here! 😅

Apparently, optional parameters become mandatory after being compiled. The V8 codepath triggers a "not enough parameters" error, which is good enough for most debugging purposes, but the emscripten codepath doesn't do anything special and silently ignores the default value, which can break any code relying on them.

The easy workaround is to override the JS methods of the affected prototypes to do this check, before calling the original function.

Add a policy for automatic return value downcasting

When augmenting a C++ class for wrapping like #35 (comment), return values of the non-augmented type should automatically downcast to the augmented type. Configured like:

method(getNode, nbind::Downcast(Node, JS_Node));

Another possible (better?) syntax would be:

NBIND_CLASS(Node) {
  downcast(JS_Node);
}

Design / performance

When using this mechanism - how are the parameters / data shared between the C++ and the Node?

For example, between .Net and C++, there is a whole marshalling (and unmarshalling) layer that sits in between, causing a big performance hit. (Try marshalling a big json/xml string between c++ and .net)

Similarly, any marshalling and unmarshalling happens here or is it a direct bind?

The reason I am asking is, to compare if it is worth using this technique or just host the c++ classes / methods directly in some custom http server. If this mechanism employs some kind of serde, then performance hiccups would be crucial.

How to handle deconstructors?

Hi,

how do I handle deconstructors?
e.g.

#include
#include

struct Greeter {
static void sayHello(std::string name) {
std::cout<< "Hello, " << name << "!\n";
}
~Greeter(void) {};
};

All the best.

Native is much slower than asmjs

The following PR lists the changes I had to make to a package to switch it to nbind (from nan). As you can see in the C source codes, I haven't made any critical change, merely changing a few function names and adding a const qualifier. However, when I tried to benchmark it, I noticed that perfs weren't as good as expected:

  • Pre-PR execution time: 3s
  • Post-PR execution time (native): 12s
  • Post-PR execution time (asmjs): 4s

As you can see, something weird is going on with the native version, which is much, much slower than even the asmjs version. I have no idea what might cause this: I checked the flags that were used when compiling it, and the -O3 flag was there without a doubt.

Have you noticed this odd disparity before?

If you want to try by yourself, you can clone [email protected]:arcanis/buffer-offset-index and run npm run install && npm run bench (assuming emcc is in your PATH).

Document the internals

Write documentation about:

  • Overall code structure.
    • Clarifying picture.
  • Code paths.
    • Class definition.
    • Constructor definition.
    • Method definition.
    • C++ class construction through JavaScript new.
    • C++ function call.
    • JavaScript callback function call.
    • Object passing by value from JavaScript to C++.
    • Object passing by value from C++ to JavaScript.
  • Data structures.
    • Storage of class definitions.
    • How different argument and return types are passed between the languages.

See Documentation so far.

Support std::map, std::set and their unordered versions

Node and all recent browsers seem to support Map and Set so std::map and std::set should be converted automatically. Probably std::map<Key, Value> should become a plain JavaScript object for any integer or string Key and otherwise a Map object.

Probably std::set<Key> should always become a JavaScript Set for performance (see anvaka/set-vs-object) but accept plain objects as input if Key is integer or string. Any truthy value in the JavaScript object would mean its key is a set member.

Windows - overriding nbind RTTI setting

I made a comment on this closed issue about not being to override RTTI... nodejs/node-gyp#26

I'm using nbind on Windows 64-bit (with Electron). I later realized it appears nbind has it's own gypi (nbind.gypi) that seems to replace (or override?) the common.gypi that TooTallNate refers to in the above link. I could not override the default "false" RTTI setting using the methods he posted, but I was able to get past my problem (but not in an ideal way) by modifying nbind.gypi to have "true" (instead of default "false") for RuntimeTypeInformation setting. Is there a way to override this setting without having to modify nbind's infrastructure code?

Memory corruption on const functions w/ Emscripten

I'm not sure if the issue comes from nbind or emscripten itself. Here is a minimal testcase repository to help debug this issue: https://github.com/arcanis/nbind-weird-behaviour (c file / js file).

When I run the code (npm start), I get the following:

client side row 42
client side column 66
row 255
column 0
row 0
column 712
row 0
column 712
row 712
column 3724
row 712
column 3724
row 3724
column 752
row 3724
column 752
row 752
column 3690
row 752
column 3690
row 3690
column 48
row 3690
column 48
row 48
column 0
row 48
column 0
row 0
column 752
row 0
column 752
row 752
column 3607

As you can see, as the test function gets called, the data it prints begin to change (but it worth noting that even during the first run, they're wrong). I'm not sure what might cause this, especially since this function shouldn't have any side effect :(

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.36.0
clang version 3.9.0 (https://github.com/kripken/emscripten-fastcomp-clang/ 271ce598c3d1fe74efadc254f5be1b57edea9f41) (https://github.com/kripken/emscripten-fastcomp/ 61acfb230665464544f2e8db292f8999fc3c628c) (emscripten 1.36.0 : 1.36.0)

Webpack support

I just noticed that nbind apparently isn't compatible with Webpack yet. Supporting it would be a great addition, especially since the asm.js compilation already works !

Basically, in order to be webpack-compliant, the loading should be greatly simplified to remove most of require calls, especially dynamic ones, at least in the browser codepath (Webpack can look for a "browser" property in the package.json, instead of "main"). For example, maybe by allowing nbind.init() to take an argument that would actually be the asm.js file preloaded (so that all the requirement logic could be bypassed).

Support Emscripten

This issue is here to track progress of ongoing development. nbind should support compiling with Emscripten and running the exact same code on Node.js and recent web browsers.

  • Static methods.
  • Numeric argument and return types.
  • Pointers wrapped as objects.
  • Constructors.
  • Destructors.
  • Non-static methods.
  • String argument and return types.
  • Getters and setters.
  • Callbacks.
  • ...without leaking handles.
  • Value types.
  • ...with MethodResultConverter.
  • ...without leaking handles.
  • Vectors.
  • Load Emscripten module through require('nbind').
  • Integrate Emscripten to Autogypi build system.
  • Fix cflags in nbind.gypi to find --js-library inside nbind.
  • Test building on Windows.
  • Add to Travis.
  • Add to AppVeyor.

Callbacks lifetime

Hi, I'm planning on using nbind to write libui bindings for node.
nbind will greatly simplify the job, but I will need to use callbacks for UI events...

Warning: currently callbacks have a very short lifetime! They can be called only until the first function that received them returns. That means it's possible to create a function like Array.map which calls a callback zero or more times and then returns, never using the callback again. It's currently not possible to create a function like setTimeout which calls the callback after it has returned.

Will this limitations of callbacks usage be removed in near future? There is some known workaround to make them work (as in setTimeout usage)?

NBIND_ERR doesn't copy the character array

Great library, seems to be very useful!

I noticed the hard way that NBIND_ERR neither copies nor releases the string passed in, so it relies on the caller to somehow manage the lifetime of the buffer until it is no longer required by nbind. This seems fairly impractical, so the functionality is only really usable with literals.
It may be sufficient to mention this in the documentation or simply replace Status::message by a std::string?

Also, would it be possible to provide something like NBIND_LOG as an easy way to log messages during development?

Function return type of size_t doesn't compile

Changing the return type of
static int strLengthStatic(const char* x) { return strlen(x); }
in test/PrimitiveMethods.cc to size_t
static size_t strLengthStatic(const char* x) { return strlen(x); }

causes the following build error:

include/nbind/v8/ValueObj.h(53): error C2228: left of '.toJS' must have class/struct/union [test/build/nbind.vcxproj]
include/nbind/v8/ValueObj.h(53): note: type is 'size_t'
include/nbind/v8/ValueObj.h(46): note: while compiling class template member function 'nbind::WireType nbind::BindingType::toWireType(ArgType)'
with
[
ReturnType=size_t,
ArgType=size_t
]

Building with VS2015.

Example needs autogypi to build and run

When I tried the code in the Example section it failed with the following output:

gyp ERR! configure error 
gyp ERR! stack Error: `gyp` failed with exit code: 1
gyp ERR! stack     at ChildProcess.onCpExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:357:16)
gyp ERR! stack     at ChildProcess.emit (events.js:110:17)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:1074:12)
gyp ERR! System Darwin 14.3.0
gyp ERR! command "node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/brodybits/mynb/bt
gyp ERR! node -v v0.12.7
gyp ERR! node-gyp -v v2.0.2
gyp ERR! not ok 

I had to first do npm install -g autogypi and run autogypi, then the example worked for me. Also needs a new version of npm as I said in charto/autogypi#1.

is it possible to create an executable out of created object file?

Hi,

I am trying to create an executable out of the object file (for instance ../build/Release/obj.target/nbind/cpp/JS_VG.o) in order to perform some debugging with gdb.
Replacing "-c" with "-o cpp/JS_AG" in binding.gyp does not do, what I want:
cc1plus: fatal error: Release/obj.target/nbind/cpp/JS_AG.d: No such file or directory

(By the way: Why does it say cc1plus and not g++?)

I tried doing it manually then:

g++ -DNODE_GYP_MODULE_NAME=nbind -DUSING_UV_SHARED=1 -DUSING_V8_SHARED=1 -DV8_DEPRECATION_WARNINGS=1 -D_DARWIN_USE_64_BIT_INODE=1 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DBUILDING_NODE_EXTENSION -I/Users/heumos/.node-gyp/7.0.0/include/node -I/Users/heumos/.node-gyp/7.0.0/src -I/Users/heumos/.node-gyp/7.0.0/deps/uv/include -I/Users/heumos/.node-gyp/7.0.0/deps/v8/include -I../node_modules/nan -I../node_modules/nbind/include -Os -gdwarf-2 -mmacosx-version-min=10.11 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -std=c++11 -fno-rtti -fno-threadsafe-statics -msse4.1 -fopenmp -frtti -ggdb3 -g -I../../genome-graph/ -I../../genome-graph/include -O3 -std=c++11 -MMD -MF ./Release/.deps/Release/obj.target/nbind/cpp/JS_AG.o.d.raw -o ../cpp/JS_AG.cpp Release/obj.target/nbind/cpp/JS_AG.o

But unsurprisingly the compiler, or to be precise the linker, nags about missing symbols:
Undefined symbols for architecture x86_64:
Among some symbols missing for vg the symbols for v8 engine are missing, too.
How could or would I add them into the command above?

Just for your information: I put a simple main with 'Hello World'

Is there any easier way to get my executable?

nbind::cbOutput failed to compile

It's quite weird, because it does compile on the repository I shared with you earlier, but doesn't on this one: https://github.com/arcanis/text-layout Despite the code being almost identical (https://github.com/arcanis/text-layout/blob/master/sources/Position.hh#L41-L44 vs https://github.com/arcanis/buffer-offset-index/blob/master/src/point.h#L34-L36)

I've double-checked everything for the past few hours, and dived into nbind's headers, but I've failed to completely understand the issue. Apparently, the compiler fails to find a proper BindingType<CreateValue> specialization - which makes little sense, since a very similar toJS function does work on the other repository ...

The error message is the following:

make: Entering directory '/home/arcanis/text-formatter/build'
  CXX(target) Release/obj.target/nbind/sources/nbind.o
  CXX(target) Release/obj.target/nbind/sources/TextLayout.o
In file included from ../sources/TextLayout.cc:9:
In file included from ../node_modules/nbind/include/nbind/api.h:93:
../node_modules/nbind/include/nbind/em/Callback.h:69:17: error: assigning to 'int' from incompatible type 'typename BindingType<CreateValue>::Type' (aka 'nbind::cbOutput::CreateValue')
                original.slot = jsConstructor.call<CreateValue>(args...);
                              ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../sources/./Position.hh:43:15: note: in instantiation of function template specialization 'nbind::cbOutput::operator()<const unsigned int &, const unsigned int &>' requested here
        output(x, y);
              ^
In file included from ../sources/TextLayout.cc:9:
In file included from ../node_modules/nbind/include/nbind/api.h:93:
../node_modules/nbind/include/nbind/em/Callback.h:28:9: error: no viable conversion from returned value of type 'int' to function return type 'typename BindingType<CreateValue>::Type' (aka 'nbind::cbOutput::CreateValue')
                return(Caller<ReturnType>::call(handle.getNum(), std::forward<Args>(args)...));
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../node_modules/nbind/include/nbind/em/Callback.h:69:33: note: in instantiation of function template specialization 'nbind::cbFunction::call<nbind::cbOutput::CreateValue, const unsigned int &, const unsigned int &>' requested here
                original.slot = jsConstructor.call<CreateValue>(args...);
                                              ^
../sources/./Position.hh:43:15: note: in instantiation of function template specialization 'nbind::cbOutput::operator()<const unsigned int &, const unsigned int &>' requested here
        output(x, y);
              ^
../node_modules/nbind/include/nbind/em/Callback.h:57:9: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const nbind::cbOutput::CreateValue &' for 1st argument
        struct CreateValue {};
               ^
../node_modules/nbind/include/nbind/em/Callback.h:57:9: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'nbind::cbOutput::CreateValue &&' for 1st argument
        struct CreateValue {};
               ^
2 errors generated.
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting

Support for events?

Hi,

Is there a way for JS to subscribe to a C++ event? For example this MSDN snippet:

// mcppv2_events.cpp
// compile with: /clr
using namespace System;

// declare delegates
delegate void ClickEventHandler(int, double);
delegate void DblClickEventHandler(String^);

// class that defines events
ref class EventSource {
public:
   event ClickEventHandler^ OnClick;   // declare the event OnClick
   event DblClickEventHandler^ OnDblClick;   // declare OnDblClick

   void FireEvents() {
      // raises events
      OnClick(7, 3.14159);
      OnDblClick("Hello");
   }
};

// class that defines methods that will called when event occurs
ref class EventReceiver {
public:
   void OnMyClick(int i, double d) {
      Console::WriteLine("OnClick: {0}, {1}", i, d);
   }

   void OnMyDblClick(String^ str) {
      Console::WriteLine("OnDblClick: {0}", str);
   }
};

int main() {
   EventSource ^ MyEventSource = gcnew EventSource();
   EventReceiver^ MyEventReceiver = gcnew EventReceiver();

   // hook handler to event
   MyEventSource->OnClick += gcnew ClickEventHandler(MyEventReceiver, &EventReceiver::OnMyClick);
   MyEventSource->OnDblClick += gcnew DblClickEventHandler(MyEventReceiver, &EventReceiver::OnMyDblClick);

   // invoke events
   MyEventSource->FireEvents();

   // unhook handler to event
   MyEventSource->OnClick -= gcnew ClickEventHandler(MyEventReceiver, &EventReceiver::OnMyClick);
   MyEventSource->OnDblClick -= gcnew DblClickEventHandler(MyEventReceiver, &EventReceiver::OnMyDblClick);
}

How would I use nbind to get OnClick-events to register on the JS side?

Save persistent instances of class pointers.

I need to save persistent instances of class pointers to avoid them being garbage collected if they are no more referenced by javascript.

I made some attempt using Persistent handles, but I was unsuccessful.
There is an easy way to do this, similar to what we can do with callbacks?

function macro conflict

There is a type std::function in the standard header your "function" macro conflicts with.
This is quite ugly, basically I have to #undef function and redefine it with a different name after including the nbind header.

There are a few other macro names that I find too generic, especially "args", "inherit", "method", "field", "getter".
I do realize these are convenient but there is a high risk of conflicting with other libs. "function" conflicting with a standard library is extra-bad imho.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.