{"id":13465053,"url":"https://github.com/cmake-js/fastcall","last_synced_at":"2025-12-26T11:05:21.501Z","repository":{"id":46246210,"uuid":"65500867","full_name":"cmake-js/fastcall","owner":"cmake-js","description":"fastcall - Fast, dyncall based foreign function interface library for Node.js","archived":false,"fork":false,"pushed_at":"2021-11-04T12:08:43.000Z","size":1380,"stargazers_count":201,"open_issues_count":35,"forks_count":16,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-05-08T23:07:52.786Z","etag":null,"topics":["ffi-wrapper","nodejs"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/fastcall","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cmake-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-08-11T20:53:57.000Z","updated_at":"2024-02-29T07:50:27.000Z","dependencies_parsed_at":"2022-09-19T07:30:40.859Z","dependency_job_id":null,"html_url":"https://github.com/cmake-js/fastcall","commit_stats":null,"previous_names":["unbornchikken/fastcall"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmake-js%2Ffastcall","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmake-js%2Ffastcall/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmake-js%2Ffastcall/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmake-js%2Ffastcall/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmake-js","download_url":"https://codeload.github.com/cmake-js/fastcall/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230494921,"owners_count":18235046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi-wrapper","nodejs"],"created_at":"2024-07-31T14:00:56.293Z","updated_at":"2025-12-26T11:05:21.425Z","avatar_url":"https://github.com/cmake-js.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/cmake-js/fastcall.svg?branch=master)](https://travis-ci.org/cmake-js/fastcall)\n\n# TOC\n\n\u003c!-- TOC --\u003e\n\n- [TOC](#toc)\n- [About](#about)\n    - [Why?](#why)\n    - [Features](#features)\n    - [Requirements](#requirements)\n    - [Install](#install)\n    - [Clone and Build](#clone-and-build)\n- [Benchmarks](#benchmarks)\n- [Documentation and Tutorials](#documentation-and-tutorials)\n    - [fastcall.Library](#fastcalllibrary)\n        - [ref](#ref)\n        - [declaring functions](#declaring-functions)\n        - [declaring structs and unions](#declaring-structs-and-unions)\n        - [declaring arrays](#declaring-arrays)\n        - [declaring everything :)](#declaring-everything-)\n        - [callbacks](#callbacks)\n        - [pointer factories](#pointer-factories)\n    - [RAII](#raii)\n        - [Disposable](#disposable)\n        - [automatic cleanup (GC)](#automatic-cleanup-gc)\n        - [scopes](#scopes)\n    - [node-ffi compatible interface](#node-ffi-compatible-interface)\n- [Showcase](#showcase)\n- [Credits](#credits)\n- [License](#license)\n\n\u003c!-- /TOC --\u003e\n\n# About\n\n**fastcall** is a foreign function interface library which aim is to provide an easy to use, 100% JavaScript based method for developers to use native shared libraries in Node.js, without needing to touch anything in C++ and without sacrificing too much performance. It's designed with performance and simplicity in mind, an it has comparable function call overhead with hand made C++ native modules. See the [benchmarks](#benchmarks).\n\n## Why?\n\nThere is a a popular dynamic binding library for Node.js:\n[node-ffi](https://github.com/node-ffi/node-ffi). Then why we need another one could ask? For performance! There is a good 20x-40x\nfunction call performance overhead when using [node-ffi](https://github.com/node-ffi/node-ffi) compared to hand made C++ native module, which is unacceptable in most cases (see the [benchmarks](#benchmarks)).\n\n## Features\n\n- uses [CMake.js](https://github.com/cmake-js/cmake-js) as of its build system (has no Python 2 dependency)\n- based on TooTallNate's excellent [ref](http://tootallnate.github.io/ref/) module and its counterparts ([ref-struct](https://github.com/TooTallNate/ref-struct), [ref-array](https://github.com/TooTallNate/ref-array) and [ref-union](https://github.com/TooTallNate/ref-union)), it doesn't try to reinvent the wheel\n- has an almost 100% [node-ffi](https://github.com/node-ffi/node-ffi) compatible interface, could work as a drop-in replacement of [node-ffi](https://github.com/node-ffi/node-ffi)\n- RAII: supports deterministic scopes and automatic, GC based cleanup\n- supports thread synchronization of asynchronous functions\n\n## Requirements\n\n- [CMake](http://www.cmake.org/download/)\n- A proper C/C++ compiler toolchain of the given platform\n    - **Windows**:\n        - [Visual C++ Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools)\n        or a recent version of Visual C++ will do ([the free Community](https://www.visualstudio.com/products/visual-studio-community-vs) version works well)\n    - **Unix/Posix**:\n        - Clang or GCC\n        - Ninja or Make (Ninja will be picked if both present)\n\n## Install\n\n```bash\nnpm install --save fastcall\n```\n\n## Clone and Build\n\n```bash\ngit clone --recursive https://github.com/cmake-js/fastcall.git\ncd fastcall\nnpm install\n```\n\nFor subsequent builds, type:\n\n```bash\ncmake-js compile\n```\n\nBut don't forget to install [CMake.js](https://github.com/cmake-js/cmake-js) as a global module first:\n\n```bash\nnpm install -g cmake-js\n```\n\n# Benchmarks\n\nTo run benchmarks, type:\n\n```bash\nnode benchmarks\n```\n\nResults:\n\n![Results](https://raw.githubusercontent.com/cmake-js/fastcall/master/benchmarkresult.png)\n\nThere are 3 tests with synchronous and asynchronous versions:\n\n- **addNumbers**: simple addition, intended to test function call performance\n- **concat**: string concatenation, intended to test function call performance when JavaScript string to C string marshaling required, which is costly.\n- **callback**: simple addition with callbacks, intended to test how fast native code can call JavaScript side functions\n\nAll tests implemented in:\n\n- **native**: C++ code. Assuming function call's cost is almost zero and there is no need for marshaling, its numbers shows the run time of test function bodies\n- **native module**: [Nan](https://github.com/nodejs/nan) based native module in C++. This is the reference, there is no way to be anything to be faster than this. **fastcall**'s aim is to get its performance as close as possible to this, so the overhead ratio got counted according to its numbers\n- **node-ffi**: binding with node-ffi in pure JavaScript\n- **fastcall**: binding with **fastcall** in pure JavaScript\n\nYeah, there is a room for improvement at **fastcall** side. Improving marshaling and callback performance is the main target of the future development.\n\n# Documentation and Tutorials\n\n## fastcall.Library\n\nCentral part of **fastcall** is the `Library` class. With that you can load shared libraries to Node.js' address spaces, and could access its functions and declared types.\n\n```js\nclass Library {\n\tconstructor(libPath, options);\n\n\tisSymbolExists(name);\n\n\trelease();\n\n\tdeclare(); declareSync(); declareAsync();\n\n\tfunction(); syncFunction(); asyncFunction();\n\n\tstruct();\n\n\tunion();\n\n\tarray();\n\n\tcallback();\n\n\tget functions();\n\n\tget structs();\n\n\tget unions();\n\n\tget arrays();\n\n\tget callbacks();\n\n\tget interface();\n}\n```\n\n**Constructor:**\n\n- `libPath`: path of the shared library to load. There is no magical platform dependent extension guess system, you should provide the correct library paths on each supported platforms (`os` module would help). For example, for OpenCL, you gotta pass `OpenCL.dll` on Windows, and `libOpenCL.so` on Linux, and so on.\n- `options`: optional object with optional properties of:\n\t- `defaultCallMode`: either the default `Library.callMode.sync`, which means synchronous functions will get created, or `Library.callMode.async` which means asynchronous functions will get created by default\n\t- `syncMode`: either the default `Library.syncMode.lock`, which means asynchronous function invocations will get synchronized with a **library global mutex**, or `Library.syncMode.queue` which means asynchronous function invocations will get synchronized with a **library global call queue** (more on that later)\n\n**Methods:**\n\n- `isSymbolExists`: returns true if the specified symbol exists in the library\n- `release`: release loaded shared library's resources (please note that `Library` is not a `Disposable` because you'll need to call this method in very rare situations)\n- `declare`: parses and process a declaration string. Its functions are declared with the default call mode\n- `declareSync`: parses and process a declaration string. Its functions are declared as synchronous\n- `declareAsync`: parses and process a declaration string. Its functions are declared as asynchronous\n- `function`: declares a function with the default call mode\n- `syncFunction`: declares a synchronous function\n- `asyncFunction`: declares an asynchronous function\n- `struct`: declares a structure\n- `union`: declares an union\n- `array`: declares an array\n- `callback`: declares a callback\n\n**Properties:**\n\n- `functions`: declared functions (metadata)\n- `structs`: declared structures (metadata)\n- `unions`: declared unions (metadata)\n- `arrays`: declared arrays (metadata)\n- `callbacks`: declared callbacks (metadata)\n\n### ref\n\nLet's take a look at [ref](http://tootallnate.github.io/ref/) before going into the details (credits for [TooTallNate](https://github.com/TooTallNate)). **ref** is a native type system with pointers and other types those are required to address C based interfaces of native shared libraries. It also has a native interface compatible types for [structs](https://github.com/TooTallNate/ref-struct), [unions](https://github.com/TooTallNate/ref-union) and [arrays](https://github.com/TooTallNate/ref-array).\n\nIn **fastcall** there are a **bundled versions** of [ref](https://github.com/TooTallNate/ref), [ref-array](https://github.com/TooTallNate/ref-array), [ref-struct](https://github.com/TooTallNate/ref-struct) and [ref-union](https://github.com/TooTallNate/ref-union). Those are 100% compatible with the originals, they are there because I didn't wanted to have a [CMake.js](https://github.com/cmake-js/cmake-js) based module to depend on anything node-gyp based stuff. Bundled versions are built with [CMake.js](https://github.com/cmake-js/cmake-js). The only exception is [ref-array](https://github.com/TooTallNate/ref-array), **fastcall**'s version contains some interface breaking changes for the sake of a way much better performance.\n\n```js\nconst fastcall = require('fastcall');\n\n// 100% ref@latest built with CMake.js:\nconst ref = fastcall.ref;\n\n// 100% ref-struct@latest\nconst StructType = fastcall.StructType;\n\n// 100% ref-union@latest\nconst UnionType = fastcall.UnionType;\n\n// modified ref-struct@latest\nconst ArrayType = fastcall.ArrayType;\n```\n\n**ref-array changes**:\n\nSee the original FAQ there: https://github.com/TooTallNate/ref-array\n\nThere are two huge performance bottleneck exists in this module. The first is the price of array indexer syntax:\n\n```js\nconst IntArray = new ArrayType('int');\nconst arr = new IntArray(5);\narr[1] = 1;\narr[0] = arr[1] + 1;\n```\n\nThose [0] and [1] are implemented by defining Object properties named \"0\" and \"1\" respectively. For supporting a length of 100, there will be 100 properties created on the fly. On the other hand those indexing numbers gets converted to string on each access.\n\nBecause of that, **fastcall**s version uses `get` and `set` method for indexing:\n\n```js\nconst IntArray = new ArrayType('int');\nconst arr = new IntArray(5);\narr.set(1, 1);\narr.set(0, arr.get(1) + 1);\n```\nNot that nice, but way much faster than the original.\n\nThe other is the continous reinterpretation of a dynamically sized array.\n\n```js\nconst IntArray = new ArrayType('int');\nconst outArr = ref.refType(IntArray);\nconst outLen = ref.refType('uint');\n\nmyLib.getIntegers(outArr, outLen);\nconst arr = outArr.unref();\nconst len = outLen.unref();\n// arr is an IntArray with length of 0\n// but we know that after the pointer\n// there are a len number of element elements,\n// so we can do:\n\nfor (let i = 0; i \u003c len; i++) {\n\tconsole.log(arr[i]);\n}\n```\n\nSo far so good, but in each iteration `arr` will gets [reinterpreted](http://tootallnate.github.io/ref/#exports-reinterpret) to a new Buffer with a size that would provide access to an item of index `i`. That's slow.\n\nIn **fastcall**'s version array's length is writable, so you can do:\n\n```js\narr.length = len;\nfor (let i = 0; i \u003c len; i++) {\n\tconsole.log(arr.get(i));\n}\n```\nWhich means only one reinterpret, and this is a lot of faster than the original.\n\nUnfortunately those are huge interface changes, that's why it might not make it in a PR.\n\n### declaring functions\n\nThe interface uses [ref and co.](#ref) for its ABI.\n\nFor declaring functions, you can go with a [node-ffi](https://github.com/node-ffi/node-ffi/wiki/Node-FFI-Tutorial) like syntax, or with a C like syntax.\n\nExamples:\n\n```js\nconst fastcall = require('fastcall');\nconst Library = fastcall.Library;\nconst ref = fastcall.ref;\n\nconst lib = new Library('bimbo.dll')\n.function('int mul(int, int)') // arg. names could be omitted\n.function('int add(int value1, int)')\n.function('int sub(int value1, int value2)')\n.function({ div: ['int', ['int', 'int']] })\n.function('void foo(void* ptr, int** outIntPtr)')\n.function({ poo: ['pointer', [ref.types.int, ref.refType(ref.types.float)]] });\n```\n\nDeclared functions are accessible on the lib's interface:\n\n```js\nconst result = lib.interface.mul(42, 42);\n```\n\n**Sync and async**:\n\nAbout sync and async modes please refer for [fastcall.Library](#fastcalllibrary)'s documentation.\n\nIf a function is async, it runs in a **separate thread**, and the result is a Bluebird Promise.\n\n```js\nconst lib = new Library(...)\n.asyncFunction('int mul(int, int)');\n\nlib.interface.mul(42, 42)\n.then(result =\u003e console.log(result));\n```\n\nYou can always switch between a function's sync and async modes:\n\n```js\nconst lib = new Library(...)\n.function('int mul(int, int)');\n\nconst mulAsync = library.interface.mul.async;\nconst mulSync = mulAsync.sync;\nassert.strictEqual(mulSync, library.interface.mul);\nassert.strictEqual(mulAsync, mulSync.async.async.sync.async);\n```\nYou get the idea.\n\n**Concurrency and thread safety:**\n\nBy default, a library's asynchronous functions are running in parallel distributed in libuv's thread pool. So they are not thread safe.\n\nFor thread safety there are two options could be passed to [fastcall.Library](#fastcalllibrary)'s constructor: `syncMode.lock` and `syncMode.queue`.\n\nWith lock, a simple mutex will be used for synchronization. With queue, all of library's asynchronous calls are enqueued, and only one could execute at once. The former is a bit slower, but that allows synchronization between synchronous calls of the given library. However the latter will throw an exception if a synchronous function gets called while there is an asynchronous invocation is in progress.\n\n**Metadata:**\n\nIn case of:\n\n```js\nconst lib = new Library(...)\n.function('int mul(int value1, int value2)');\n```\n\n`lib.functions.mul` gives the same metadata object's instance as `lib.interface.mul.function`.\n\n**- properties:**\n\n- `name`: function's name\n- `resultType`: ref type of the function's result\n- `args`: is an array of argument objects, with properties of\n\t- `name`: name of the argument (arg[n] when the name was omitted)\n\t- `type`: ref type of the given argument\n\n**- methods**\n\n- `toString`: gives function's C like syntax\n\n### declaring structs and unions\n\nEasy as goblin pie. (Note: struct interface is [ref-struct](#ref), and union is [ref-array](#ref) based.)\n\nYou can go with the traditional (node-ffi) way:\n\n```js\nconst fastcall = require('fastcall');\nconst StructType = fastcall.StructType;\n\n// Let's say you have a library with a function of:\n// float dist(Point* p1, Pint* p2);\n\nconst Point = new StructType({\n\tx: 'int',\n\ty: 'int'\n});\n\nconst lib = new Library(...)\n.function({ dist: ['float', [ref.refType(Point), ref.refType(Point)]] });\n\nconst point1 = new Point({ x: 42, y: 42 });\nconst point2 = new Point({ x: 43, y: 43 });\nconst dist = lib.interface.dist(point1.ref(), point2.ref());\n```\n\nBut there is a better option. You can declare struct on library interfaces, and this way, **fastcall** will understand JavaScript structures on function interfaces.\n\nDeclaring structures:\n\n```js\n// object syntax\nlib.struct({\n\tPoint: {\n\t\tx: 'int',\n\t\ty: 'int'\n\t}\n});\n\n// C like syntax\nlib.struct('struct Point { int x; int y; }');\n```\n\nAfter that the structure is accessible on library's `structs` property:\n\n```js\nconst pointMetadata = lib.structs.Point;\n```\n\n**metadata properties**:\n\n- `name`: struct's name\n- `type`: struct's ref type (exactly like `Point` in the first example)\n\nThe real benefit is that, by this way - because the *library knows about your structure* - you can do the following:\n\n```js\nlib.function({ dist: ['float', ['Point*', 'Point*']] });\n\n// --- OR ---\n\nlib.function('float dist(Point* point1, Point* point2)');\n\n// --- THEN ---\n\nconst result =\n\tlib.interface.mul({ x: 42, y: 42 }, { x: 43, y: 43 });\n```\n\nWay much nicer and simpler syntax like the original, ain't it?\n\n**About unions:**\n\nDeclaring unions is exactly the same, except 'union' used instead of 'struct' on appropriate places. (Note: struct interface is [ref-union](#ref) based.)\n\n```js\nlib\n.union('union U { int x, float y }')\n.function('float pickFloatPart(U* u)');\n\nconst f = lib.interface.pickFloatPart({ y: 42.2 });\n\n// f is 42.2\n```\n\n### declaring arrays\n\nDeclaring arrays is not much different than declaring structures and unions. There is one difference: arrays with fixed length are supported.\n\n```c\n// C code:\n\n// a struct using fixed length array\nstruct S5 {\n\tint fiveInts[5];\n};\n\n// a astruct using an arbitrary length array\nstruct SA {\n\tint ints[]; // or: int* ints;\n};\n\n// example functions:\n\n// prints five values\nvoid printS5(S5* s);\n\n// print length number of values\n// length is a parameter, because SA knows nothing about\n// the length of SA.ints\nvoid printSA(SA* s, int length);\n```\n\nAccess those in **fastcall**:\n\n```js\nlib\n.array('int[] IntArray') // arbitrary length\n.struct('struct S5 { IntArray[5] ints; }')\n.struct('struct SA { IntArray[] ints; }') // or: IntArray ints\n.function('void printS5(S5* s)')\n.function('void printSA(SA* s, int len)');\n\nlib.interface.printS5({ ints: [1, 2, 3, 4, 5] });\nlib.interface.printSA({ ints: [1, 2, 3] }, 3);\n```\n\nOf course object syntax is available too:\n\n```js\nlib\n.array({ IntArray: 'int' }) // arbitrary length\n.struct({ S5: { ints: 'IntArray[5]' } })\n.struct({ SA: { ints: 'IntArray' } })\n.function({ printS5: ['void', ['IntArray[5]']] })\n.function({ printSA: ['void', ['IntArray', 'int']] });\n```\n\nAfter that the array is accessible on library's `arrays` property:\n\n```js\nconst intArrayMetadata = lib.arrays.IntArray;\n```\n\n**metadata properties**:\n\n- `name`: array's name\n- `length`: number if fixed length, null if arbitrary\n- `type`: array's ref type\n\nOf course you can declare fixed length arrays directly:\n\n```js\nlib.array('int[4] IntArray4');\n```\n\nAnd any fixed or arbitrary length array type could get resized on usage:\n\n```js\nlib\n.struct('struct S5 { IntArray4[5] ints; }')\n.struct('struct SA { IntArray4[] ints; }')\n```\n\n### declaring everything :)\n\n[fastcall.Library](#fastcalllibrary)'s `declare`, `declareSync` and `declareAsync` functions could declare every type of stuff at once.\n\nSo the array example could be written like:\n\n```js\nlib.declare('int[] IntArray;' +\n\t'struct S5 { IntArray[5] ints; };' +\n\t'struct SA { IntArray[] ints; };' +\n\t'void printS5(S5* s);' +\n\t'void printSA(SA* s, int len);');\n```\n\n### callbacks\n\nYou can create native pointers for arbitrary JavaScript functions, and by this way you can use JavaScript functions for native callbacks.\n\n```C\n// C code\n\ntypedef int (*TMakeIntFunc)(float, double);\n\nint bambino(float fv, double dv, TMakeIntFunc func)\n{\n    return (int)func(fv, dv) * 2;\n}\n```\n\nTo drive this, you need a callback and a function on your **fastcall** based library defined. It could get declared by object syntax:\n\n```js\nlib\n.callback({ TMakeIntFunc: ['int', ['float', 'double']] })\n.function({ bambino: ['int', ['float', 'double', 'TMakeIntFunc']] });\n\nconst result = lib.interface.bambino(19.9, 1.1, (a, b) =\u003e a + b);\n// result is 42\n```\n\nOr with a familiar, C like syntax:\n\n```js\nlib\n.declare('int (*TMakeIntFunc)(float, double);' +\n\t'int bambino(float fv, double dv, TMakeIntFunc func)');\n\nconst result = lib.interface.bambino(19.9, 1.1, (a, b) =\u003e a + b);\n// result is 42\n```\n\nCallback's metadata are accessible on library's `callbacks` property:\n\n```js\nconst TMakeIntFuncMetadata = lib.callbacks.TMakeIntFunc;\n```\n\n**- metadata properties:**\n\n- `name`: callbacks's name\n- `resultType`: ref type of the callbacks's result\n- `args`: is an array of argument objects, with properties of\n\t- `name`: name of the argument (arg[n] when the name was omitted)\n\t- `type`: ref type of the given argument\n\n**- methods**\n\n- `toString`: gives callbacks C like syntax\n\n### pointer factories\n\nIf you wanna use you callbacks, structs, unions or arrays more than once (in a loop, for example), without being changed, you can create a ([ref](#ref)) pointer from them, and with those, function call performance will be significantly faster. Callback, struct, union and array factories are just functions on library's property: `interface`.\n\nFor example:\n\n```js\n// ref-struct way\n\nconst StructType = require('fastcall').StructType; // or require('ref-struct')\nconst MyStruct = new StructType({ a: 'int', b: 'double' });\n\nconst struct = new MyStruct({ a: 1, b: 1.1 });\nconst ptr = struct.ref(); // ptr instanceof Buffer\n\nlib.interface.printStruct(ptr);\n\n// fastcall way\n\nlib.declare('struct StructType { int a; double b; }');\n\nconst ptr = lib.interface.StructType({ a: 1, b: 1.1 });\n// ptr instanceof Buffer\n\n// You can create the modifyable struct instance of course\n// by using the metadata property: type\n\nconst structMetadata = lib.structs.StructType;\nconst struct = structMetadata.type({ a: 1, b: 1.1 });\n// ...\nstruct.a = 2;\nstruct.b = 0.1;\n// ...\nconst ptr = struct.ref();\n// or\nconst ptr = lib.interface.StructType(struct);\n```\n\nOr with callbacks:\n\n```js\nlib.declare('void (*CB)(int)');\n\nconst callbackPtr = lib.interface.CB(x =\u003e x * x);\n// callbackPtr instanceof Buffer\n\nlib.interface.someNativeFunctionWithCallback(42, callbackPtr);\n// that's a slightly faster than:\nlib.interface.someNativeFunctionWithCallback(42, x =\u003e x * x);\n```\n\n**string pointers**:\n\nFor converting JavaScript string to ([ref](#ref)) pointers back and forth there are [ref.allocCString()](http://tootallnate.github.io/ref/#exports-allocCString) and [ref.readCString()](http://tootallnate.github.io/ref/#extensions-readCString) methods available.\n\nHowever for converting JavaScript strings to native-side **read-only** strings there is a much faster alternative available in **fastcall**:\n\n`fastcall.makeStringBuffer([string] str)`\n\nExample:\n\n```js\nconst fastcall = require('fastcall');\n// ...\n\nlib.declare('void print(char* str)');\n\nconst ptr = fastcall.makeStringBuffer(\n\t'Sárgarigó, madárfészek, ' +\n\t'az a legszebb, aki részeg');\n\nlib.interface.print(ptr);\n// that's faster than writing:\nlib.interface.print(\n\t'Sárgarigó, madárfészek, ' +\n\t'az a legszebb, aki részeg');\n```\n\n## RAII\n\nNative resources must get freed somehow. We can rely on Node.js' garbage collector for this task, but that would only work if our native code's held resources are memory blocks. For other resources it is more appropriate to free them manually, for example in try ... finally blocks. However, there are more complex cases.\n\nLet's say we have a math library that works on the GPU with vectors and matrices. A complex formula will create a bunch of temporary vectors and matrices, that will hold a lot memory on the GPU. In this case, we cannot rely on garbage collector of course, because that knows nothing about VRAM. Decorating our formula with try ... finally blocks would be a horrible idea in this complex case, just think about it:\n\n```js\nconst vec1 = lib.vec([1, 2, 3]);\nconst vec2 = lib.vec([4, 5, 6]);\nconst result = lib.pow(lib.mul(vec1, vec2), lib.abs(lib.add(vec1, vec2)));\n\n// would be something like:\n\nconst vec1 = lib.vec([1, 2, 3]);\nconst vec2 = lib.vec([4, 5, 6]);\nlet tmpAdd = null, tmpAbs = null, tmpMul = null;\nlet result;\ntry {\n\ttmpAdd = lib.add(vec1, vec2);\n\ttmpAbs = lib.abs(tmpAdd);\n\ttmpMul = lib.mul(vec1, vec2);\n\tresult = lib.pow(tmpMul, tmpAbs);\n}\nfinally {\n\ttmpAdd \u0026\u0026 tmpAdd.free();\n\ttmpMul \u0026\u0026 tmpMul.free();\n\ttmpAbs \u0026\u0026 tmpAbs.free();\n}\n```\nSo we need an automatic, deterministic scoping mechanism for JavaScript for supporting this case. Like C++ RAII or Python's `__del__` method.\n\nThe good news is all three mentioned techniques are supported in **fastcall**.\n\n### Disposable\n\nFor accessing **fastcall**'s RAII features you need a class that inherits from `Disposable`. It's a very simple class:\n\n```js\nclass Disposable {\n\tconstructor(disposeFunction, aproxAllocatedMemory);\n\n\tdispose();\n\n\tresetDisposable(disposeFunction, aproxAllocatedMemory);\n}\n```\n\n- `disposeFunction`: could be null or a function. If null, then `Disposable` doesn't dispose anything. If a function, then it should release your object's native resources. **It could be asynchronous**, and should return a Promise on that case (any *thenable* object will do). Please note that this function has no parameters, and only allowed to capture native handles from the source object, not a reference of the source itself because that would prevent garbage collection! More on this later, please keep reading!\n- `aproxAllocatedMemory`: in bytes. You could inform Node.js' GC about your object's native memory usage (calls [Nan::AdjustExternalMemory()](https://github.com/nodejs/nan/blob/master/doc/v8_internals.md#api_nan_adjust_external_memory)). Will get considered only if it's a positive number.\n- `dispose()`: will invoke `disposeFunction` manually (for the mentioned try ... catch use cases). Subsequent calls does nothing. You can override this method for implementing custom disposing logic, just don't forget to call its prototype's `dispose()` if you passed a `disposeFunction` to `super`. If `disposeFunction` is asynchronous then `dipsose()` should be asynchronous too by returning a Promise (or any *thenable* object).\n- `resetDisposable(...)`: reinitializes the dispose function and the allocated memory of the given `Disposable`. You should call this, when the underlying handle changed. *WARNING*: the original `disposeFunction` is not called implicitly by this method. You can rely on garbage collector to clean it up, or you can call `dispose()` explicitly prior calling of this method.\n\nExample:\n\n```js\nconst lib = require('lib');\nconst fastcall = require('fastcall');\nconst ref = fastcall.ref;\nconst Disposable = fastcall.Disposable;\n\nclass Stuff {\n\tconstructor() {\n\t\tconst out = ref.alloc('void*');\n\t\tlib.createStuff(out);\n\t\tconst handle = out.defer();\n\t\tsuper(\n\t\t\t() =\u003e {\n\t\t\t\t// you should NEVER mention \"this\" there\n\t\t\t\t// that would prevent garbage collection\n\t\t\t\tlib.releaseStuff(handle);\n\t\t\t},\n\t\t\t42 /*Bytes*/);\n\t\tthis.handle = handle;\n\t}\n}\n\n// later\n\nlet stuff = null;\ntry {\n\tstuff = new Stuff();\n\t// do stuff :)\n}\nfinally {\n\tstuff \u0026\u0026 stuff.dispose();\n}\n\n// replace the underlying handle:\n\nconst stuff = new Stuff();\n\n// get some native handle from anywhere\nconst out = ref.alloc('void*');\nlib.createStuff(out);\nconst someOtherHandle = out.defer();\n\n// now, stuff should wrap that\n\n// you should implement this in a private method:\nstuff.dispose(); // old handle gets released\nstuff.resetDisposable(() =\u003e lib.releaseStuff(someOtherHandle), 42);\nstuff.handle = someOtherHandle;\n```\nFor prototype based inheritance please use `Disposable.Legacy` as the base class:\n\n```js\nfunction Stuff() {\n\tDisposable.Legacy.call(this, ...);\n}\n\nutil.inherits(Stuff, Disposable.Legacy);\n```\n\n### automatic cleanup (GC)\n\nWhen there is no alive references exist for your objects, they gets disposed automatically once Node.js' GC cycle kicks in (`lib.releaseStuff(handle)` would get called from the above example). There is nothing else to do there. :) (Reporting approximate memory usage would help in this case, though.)\n\n### scopes\n\nFor deterministic destruction without that try ... catch mess, **fastcall** offers scopes. Let's take a look at an example:\n\n```js\nconst scope = require('fastcall').scope;\n\n// Let's say, we have Stuff class\n// from the previous example.\n\nscope(() =\u003e {\n\tconst stuff1 = new Stuff();\n\t// do stuff :)\n\treturn scope(() =\u003e {\n\t\tconst stuff2 = new Stuff();\n\t\tconst stuff3 = new Stuff();\n\t\tconst stuff4 = fuseStuffs(/*tmp*/fuseStuff(stuff1, stuff2), stuff3);\n\t\treturn stuff4;\n\t});\n});\n```\n\nKinda C++ braces.\n\n**Rules:**\n\n- scope only affects objects whose classes inherits from `Disposable`, we refer them as *disposables* from now on\n- scope will affect implicitly created disposables also (like that hidden temporary result of the inner `fuseStuff` call of the above example)\n- all disposables gets disposed on the end of the scope, except returned ones\n- returned disposables are propagated to parent scope, if there is one - if there isn't a parent, they *escape* (see below)\n\n**Escaping and compound disposables:**\n\nA disposable could escape from a nest of scopes at anytime. This will be handy for creating classes those are a compound of other disposables. Escaped disposable would become a free object that won't get affected further by the above rules. (They would get disposed manually or by the garbage collector eventually.)\n\n```js\nclass MyClass extends Disposable {\n\tconstructor() {\n\t\t// MyClass is disposable but has no\n\t\t// direct native references,\n\t\t// so its disposeFunction is null\n\t\tsuper(null);\n\n\t\tthis.stuff1 = null;\n\t\tthis.stuff2 = null;\n\t\tscope(() =\u003e {\n\t\t\tconst stuff1 = new Stuff();\n\t\t\t// do stuff :)\n\t\t\tthis.stuff1 = scope.escape(stuff1);\n\t\t\tconst tmp = new Stuff();\n\t\t\tthis.stuff2 = scope.escape(fuseStuffs(tmp, stuff1));\n\t\t});\n\t\t// at this point this.stuff1 and\n\t\t// this.stuff2 will be alive\n\t\t// despite their creator scope got ended\n\t}\n\n\tdispose() {\n\t\t// we should override dispose() to\n\t\t// free our custom objects\n\t\tthis.stuff1.dispose();\n\t\tthis.stuff2.dispose();\n\t}\n}\n\n// later\n\nscope(() =\u003e {\n\tconst poo = new MyClass();\n\t// so this will open a child scope in\n\t// MyClass' constructor that frees its\n\t// temporaries automatically.\n\t// MyClass.stuff1 and MyClass.stuff2 escaped,\n\t// so they has nothing to do with the current scope.\n});\n// However poo got created in the above scope,\n// so it gets disposed at the end,\n// and MyClass.stuff1 and MyClass.stuff2 gets disposed at that point\n// because of the overridden dispose().\n```\n\n**Result:**\n\n`scope`'s result is the result of its function.\n\n```js\nconst result = scope(() =\u003e {\n\treturn new Stuff();\n});\n// result is the new Stuff\n```\nRules of propagation is described above. Propagation also happens when the function returns with:\n\n- an array of disposables\n- a plain objects holding disposables in its values\n- Map of disposables\n- Set of disposables\n\nThis lookup is **recursive**, and apply for `scope.escape()`'s argument, so you can escape an array of Map of disposables for example with a single `scope.escape()` call.\n\n**Async:**\n\nIf a scope's function returns a promise (any then-able object will do) then it turns to an asynchronous scope, it also returns a promise. Same rules apply like with synchronous scopes.\n\n```js\nconst result = scope(() =\u003e\n\tlib.loadAsync()\n\t.then(loaded =\u003e {\n\t\t// do something with loaded ...\n\t\treturn new Stuff();\n\t}));\n\nresult.then(result =\u003e {\n\t// result is the new Stuff\n});\n```\n\n**Coroutines**:\n\nCoroutines supported by calling `scope.async`. So the above example turns to:\n\n```js\nconst result = yield scope.async(function* () {\n\tconst loaded = yield lib.loadAsync();\n\treturn new Stuff();\n})\n```\n\nWay much nicer, eh? It does exactly the same thing.\n\n## node-ffi compatible interface\n\nIf you happen to have a node-ffi based module, you can switch to **fastcall** with a minimal effort, because there is a node-ffi compatible interface available:\n\n```js\nconst fastcall = require('fastcall');\n\n// in\nconst ffi = fastcall.ffi;\n\n// you'll have\nffi.Library\nffi.Function\nffi.Callback\nffi.StructType // == fastcall.StructType (ref-struct)\nffi.UnionType // == fastcall.UnionType (ref-union)\nffi.ArrayType // == fastcall.ArrayType (ref-array)\n```\n\nWorks exactly like [node-ffi](https://github.com/node-ffi/node-ffi) and [ref](#ref) modules. However there are some minor exceptions:\n\n- only `async` option supported in library options\n- `asyncPromise` property is available in functions along with `async`, you don't have to rely `Promise.promisify()` like features\n- **fastcall**'s version of Library doesn't add default extensions and prefixes to shared library names, so `\"OpenCL\"` won't turn magically to `\"OpenCL.dll\"` on windows or `\"libOpenCL.so\"` on Linux\n- **fastcall**'s version of [ref-array is modified slightly to have better performance than the original](#ref)\n\n# Showcase\n\n- [NOOOCL](https://github.com/unbornchikken/NOOOCL): I have recently ported NOOOCL from node-ffi to **fastcall**. It took only a hour or so thanks to **fastcall**'s node-ffi compatible interface. Take a look at its source code to have a better idea how ref and **fastcall** works together in a legacy code.\n- [ArrayFire.js](https://github.com/arrayfire/arrayfire-js/tree/fastcall): as soon as I finish writing this documentation, I'm gonna start to work on a brand new, **fastcall** based version of ArrayFire.js. That will get implemented with **fastcall** from strach, so eventually you can take a look its source code for hints and ideas of using this library.\n\n# Credits\n\n- **Daniel Adler** and **Tassilo Philipp** - for [dyncall](http://www.dyncall.org/index)\n- [TooTallNate](https://github.com/TooTallNate) - [ref](https://github.com/TooTallNate/ref), [ref-array](https://github.com/TooTallNate/ref-array), [ref-struct](https://github.com/TooTallNate/ref-struct), [ref-union](https://github.com/TooTallNate/ref-union) and of course [node-ffi](https://github.com/node-ffi/node-ffi) for inspiration and ideas\n\n# License\n\n```\nCopyright 2016 Gábor Mező (gabor.mezo@outlook.com)\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmake-js%2Ffastcall","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmake-js%2Ffastcall","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmake-js%2Ffastcall/lists"}