koffi 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/ChangeLog.md +8 -2
  2. package/build/qemu/2.0.1/koffi_darwin_arm64.tar.gz +0 -0
  3. package/build/qemu/2.0.1/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/2.0.1/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/2.0.1/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/2.0.1/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/2.0.1/koffi_linux_arm32hf.tar.gz +0 -0
  8. package/build/qemu/2.0.1/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/2.0.1/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/2.0.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  11. package/build/qemu/2.0.1/koffi_linux_x64.tar.gz +0 -0
  12. package/build/qemu/2.0.1/koffi_openbsd_ia32.tar.gz +0 -0
  13. package/build/qemu/2.0.1/koffi_openbsd_x64.tar.gz +0 -0
  14. package/build/qemu/2.0.1/koffi_win32_arm64.tar.gz +0 -0
  15. package/build/qemu/2.0.1/koffi_win32_ia32.tar.gz +0 -0
  16. package/build/qemu/2.0.1/koffi_win32_x64.tar.gz +0 -0
  17. package/doc/benchmarks.md +2 -2
  18. package/doc/changes.md +12 -12
  19. package/doc/conf.py +14 -1
  20. package/doc/dist/doctrees/benchmarks.doctree +0 -0
  21. package/doc/dist/doctrees/changes.doctree +0 -0
  22. package/doc/dist/doctrees/environment.pickle +0 -0
  23. package/doc/dist/doctrees/functions.doctree +0 -0
  24. package/doc/dist/doctrees/index.doctree +0 -0
  25. package/doc/dist/doctrees/types.doctree +0 -0
  26. package/doc/dist/html/.buildinfo +1 -1
  27. package/doc/dist/html/_sources/benchmarks.md.txt +2 -2
  28. package/doc/dist/html/_sources/changes.md.txt +12 -12
  29. package/doc/dist/html/_sources/functions.md.txt +6 -6
  30. package/doc/dist/html/_sources/types.md.txt +10 -2
  31. package/doc/dist/html/benchmarks.html +6 -2
  32. package/doc/dist/html/changes.html +18 -14
  33. package/doc/dist/html/contribute.html +4 -0
  34. package/doc/dist/html/functions.html +10 -6
  35. package/doc/dist/html/genindex.html +4 -0
  36. package/doc/dist/html/index.html +8 -4
  37. package/doc/dist/html/memory.html +4 -0
  38. package/doc/dist/html/objects.inv +0 -0
  39. package/doc/dist/html/platforms.html +5 -1
  40. package/doc/dist/html/search.html +4 -0
  41. package/doc/dist/html/searchindex.js +1 -1
  42. package/doc/dist/html/start.html +4 -0
  43. package/doc/dist/html/types.html +20 -4
  44. package/doc/functions.md +6 -6
  45. package/doc/templates/badges.html +5 -0
  46. package/doc/types.md +11 -3
  47. package/package.json +1 -1
  48. package/src/abi_arm32.cc +1 -1
  49. package/src/abi_arm64.cc +1 -1
  50. package/src/abi_riscv64.cc +1 -1
  51. package/src/abi_x64_sysv.cc +1 -1
  52. package/src/abi_x64_win.cc +1 -1
  53. package/src/abi_x86.cc +1 -1
  54. package/src/ffi.cc +3 -3
  55. package/test/sqlite.js +5 -5
  56. package/test/sync.js +3 -1
  57. package/build/qemu/2.0.0/koffi_darwin_arm64.tar.gz +0 -0
  58. package/build/qemu/2.0.0/koffi_darwin_x64.tar.gz +0 -0
  59. package/build/qemu/2.0.0/koffi_freebsd_arm64.tar.gz +0 -0
  60. package/build/qemu/2.0.0/koffi_freebsd_ia32.tar.gz +0 -0
  61. package/build/qemu/2.0.0/koffi_freebsd_x64.tar.gz +0 -0
  62. package/build/qemu/2.0.0/koffi_linux_arm32hf.tar.gz +0 -0
  63. package/build/qemu/2.0.0/koffi_linux_arm64.tar.gz +0 -0
  64. package/build/qemu/2.0.0/koffi_linux_ia32.tar.gz +0 -0
  65. package/build/qemu/2.0.0/koffi_linux_riscv64hf64.tar.gz +0 -0
  66. package/build/qemu/2.0.0/koffi_linux_x64.tar.gz +0 -0
  67. package/build/qemu/2.0.0/koffi_openbsd_ia32.tar.gz +0 -0
  68. package/build/qemu/2.0.0/koffi_openbsd_x64.tar.gz +0 -0
  69. package/build/qemu/2.0.0/koffi_win32_arm64.tar.gz +0 -0
  70. package/build/qemu/2.0.0/koffi_win32_ia32.tar.gz +0 -0
  71. package/build/qemu/2.0.0/koffi_win32_x64.tar.gz +0 -0
package/ChangeLog.md CHANGED
@@ -2,12 +2,18 @@
2
2
 
3
3
  ## History
4
4
 
5
+ ### Koffi 2.0.1
6
+
7
+ **Main changes:**
8
+
9
+ - Return `undefined` (instead of null) for `void` functions
10
+
5
11
  ### Koffi 2.0.0
6
12
 
7
13
  **Major new features:**
8
14
 
9
- - Add disposable types for automatic disposal of C values (such as heap-allocated strings)
10
- - Add support for registered callbacks, that can be called after the initial FFI call
15
+ - Add [disposable types](functions.md#heap-allocated-values) for automatic disposal of C values (such as heap-allocated strings)
16
+ - Add support for [registered callbacks](functions.md#registered-callbacks), that can be called after the initial FFI call
11
17
  - Support named pointer types
12
18
  - Support complex type specifications outside of prototype parser
13
19
 
package/doc/benchmarks.md CHANGED
@@ -10,8 +10,8 @@ Here is a quick overview of the execution time of Koffi calls on three benchmark
10
10
 
11
11
  <table style="margin: 0 auto;">
12
12
  <tr>
13
- <td><a href="static/perf_linux_20220628.png" target="_blank"><img src="static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
14
- <td><a href="static/perf_windows_20220628.png" target="_blank"><img src="static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
13
+ <td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
14
+ <td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
15
15
  </tr>
16
16
  </table>
17
17
 
package/doc/changes.md CHANGED
@@ -76,10 +76,10 @@ For functions that return handles or pass them by parameter:
76
76
  // Koffi 1.x
77
77
 
78
78
  const FILE = koffi.handle('FILE');
79
- const fopen = lib.func('FILE fopen(const char *path, const char *mode)');
80
- const fclose = lib.func('int fclose(FILE stream)');
79
+ const fopen = lib.func('fopen', 'FILE', ['str', 'str']);
80
+ const fopen = lib.func('fclose', 'int', ['FILE']);
81
81
 
82
- let fp = fopen('touch', 'wb');
82
+ let fp = fopen('EMPTY', 'wb');
83
83
  if (!fp)
84
84
  throw new Error('Failed to open file');
85
85
  fclose(fp);
@@ -89,10 +89,10 @@ fclose(fp);
89
89
  // Koffi 2.x
90
90
 
91
91
  const FILE = koffi.handle('FILE');
92
- const fopen = lib.func('FILE *fopen(const char *path, const char *mode)');
93
- const fclose = lib.func('int fclose(FILE *stream)');
92
+ const fopen = lib.func('fopen', 'FILE *', ['str', 'str']);
93
+ const fopen = lib.func('fclose', 'int', ['FILE *']);
94
94
 
95
- let fp = fopen('touch', 'wb');
95
+ let fp = fopen('EMPTY', 'wb');
96
96
  if (!fp)
97
97
  throw new Error('Failed to open file');
98
98
  fclose(fp);
@@ -103,10 +103,10 @@ For functions that set opaque handles through output parameters (such as `sqlite
103
103
  ```js
104
104
  // Koffi 1.x
105
105
 
106
- const sqlite3_db = koffi.handle('sqlite3_db');
106
+ const sqlite3 = koffi.handle('sqlite3');
107
107
 
108
- const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(sqlite3_db), 'int', 'str']);
109
- const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [sqlite3_db]);
108
+ const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 *db, int, const char *)');
109
+ const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 db)');
110
110
 
111
111
  const SQLITE_OPEN_READWRITE = 0x2;
112
112
  const SQLITE_OPEN_CREATE = 0x4;
@@ -122,10 +122,10 @@ sqlite3_close_v2(db);
122
122
  ```js
123
123
  // Koffi 2.x
124
124
 
125
- const sqlite3_db = koffi.handle('sqlite3_db');
125
+ const sqlite3 = koffi.handle('sqlite3');
126
126
 
127
- const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(koffi.pointer(sqlite3_db, 2)), 'int', 'str']);
128
- const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [koffi.pointer(sqlite3_db)]);
127
+ const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 **db, int, const char *)');
128
+ const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 *db)');
129
129
 
130
130
  const SQLITE_OPEN_READWRITE = 0x2;
131
131
  const SQLITE_OPEN_CREATE = 0x4;
package/doc/conf.py CHANGED
@@ -21,7 +21,7 @@ extensions = [
21
21
  ]
22
22
 
23
23
  # Add any paths that contain templates here, relative to this directory.
24
- templates_path = ['_templates']
24
+ templates_path = ['templates']
25
25
 
26
26
  exclude_patterns = []
27
27
 
@@ -48,6 +48,19 @@ html_link_suffix = ''
48
48
 
49
49
  html_css_files = ['custom.css']
50
50
 
51
+ html_sidebars = {
52
+ "**": [
53
+ "sidebar/brand.html",
54
+ "sidebar/search.html",
55
+ "sidebar/scroll-start.html",
56
+ "sidebar/navigation.html",
57
+ "sidebar/ethical-ads.html",
58
+ "badges.html",
59
+ "sidebar/scroll-end.html",
60
+ "sidebar/variant-selector.html"
61
+ ]
62
+ }
63
+
51
64
  # -- MyST parser options -------------------------------------------------
52
65
 
53
66
  myst_enable_extensions = [
Binary file
Binary file
Binary file
Binary file
@@ -1,4 +1,4 @@
1
1
  # Sphinx build info version 1
2
2
  # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3
- config: 3958eced2fda3c6c0751ec1a88d416ca
3
+ config: 176d11a9c5f53cb77e2388cfd78b9cee
4
4
  tags: 645f666f9bcd5a90fca523b33c5a78b7
@@ -10,8 +10,8 @@ Here is a quick overview of the execution time of Koffi calls on three benchmark
10
10
 
11
11
  <table style="margin: 0 auto;">
12
12
  <tr>
13
- <td><a href="static/perf_linux_20220628.png" target="_blank"><img src="static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
14
- <td><a href="static/perf_windows_20220628.png" target="_blank"><img src="static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
13
+ <td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
14
+ <td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
15
15
  </tr>
16
16
  </table>
17
17
 
@@ -76,10 +76,10 @@ For functions that return handles or pass them by parameter:
76
76
  // Koffi 1.x
77
77
 
78
78
  const FILE = koffi.handle('FILE');
79
- const fopen = lib.func('FILE fopen(const char *path, const char *mode)');
80
- const fclose = lib.func('int fclose(FILE stream)');
79
+ const fopen = lib.func('fopen', 'FILE', ['str', 'str']);
80
+ const fopen = lib.func('fclose', 'int', ['FILE']);
81
81
 
82
- let fp = fopen('touch', 'wb');
82
+ let fp = fopen('EMPTY', 'wb');
83
83
  if (!fp)
84
84
  throw new Error('Failed to open file');
85
85
  fclose(fp);
@@ -89,10 +89,10 @@ fclose(fp);
89
89
  // Koffi 2.x
90
90
 
91
91
  const FILE = koffi.handle('FILE');
92
- const fopen = lib.func('FILE *fopen(const char *path, const char *mode)');
93
- const fclose = lib.func('int fclose(FILE *stream)');
92
+ const fopen = lib.func('fopen', 'FILE *', ['str', 'str']);
93
+ const fopen = lib.func('fclose', 'int', ['FILE *']);
94
94
 
95
- let fp = fopen('touch', 'wb');
95
+ let fp = fopen('EMPTY', 'wb');
96
96
  if (!fp)
97
97
  throw new Error('Failed to open file');
98
98
  fclose(fp);
@@ -103,10 +103,10 @@ For functions that set opaque handles through output parameters (such as `sqlite
103
103
  ```js
104
104
  // Koffi 1.x
105
105
 
106
- const sqlite3_db = koffi.handle('sqlite3_db');
106
+ const sqlite3 = koffi.handle('sqlite3');
107
107
 
108
- const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(sqlite3_db), 'int', 'str']);
109
- const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [sqlite3_db]);
108
+ const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 *db, int, const char *)');
109
+ const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 db)');
110
110
 
111
111
  const SQLITE_OPEN_READWRITE = 0x2;
112
112
  const SQLITE_OPEN_CREATE = 0x4;
@@ -122,10 +122,10 @@ sqlite3_close_v2(db);
122
122
  ```js
123
123
  // Koffi 2.x
124
124
 
125
- const sqlite3_db = koffi.handle('sqlite3_db');
125
+ const sqlite3 = koffi.handle('sqlite3');
126
126
 
127
- const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(koffi.pointer(sqlite3_db, 2)), 'int', 'str']);
128
- const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [koffi.pointer(sqlite3_db)]);
127
+ const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 **db, int, const char *)');
128
+ const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 *db)');
129
129
 
130
130
  const SQLITE_OPEN_READWRITE = 0x2;
131
131
  const SQLITE_OPEN_CREATE = 0x4;
@@ -160,11 +160,11 @@ This example opens an in-memory SQLite database, and uses the node-ffi-style fun
160
160
  const koffi = require('koffi');
161
161
  const lib = koffi.load('sqlite3.so');
162
162
 
163
- const sqlite3_db = koffi.handle('sqlite3_db');
163
+ const sqlite3 = koffi.handle('sqlite3');
164
164
 
165
165
  // Use koffi.out() on a double pointer to copy out (from C to JS) after the call
166
- const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(koffi.pointer(sqlite3_db, 2)), 'int', 'str']);
167
- const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [koffi.pointer(sqlite3_db)]);
166
+ const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(koffi.pointer(sqlite3, 2)), 'int', 'str']);
167
+ const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [koffi.pointer(sqlite3)]);
168
168
 
169
169
  const SQLITE_OPEN_READWRITE = 0x2;
170
170
  const SQLITE_OPEN_CREATE = 0x4;
@@ -183,7 +183,7 @@ Some C functions return heap-allocated values directly or through output paramet
183
183
 
184
184
  For opaque handles, such as FILE, this does not matter because you will explicitly call `fclose()` on them. But some values (such as strings) get implicitly converted by Koffi, and you lose access to the original pointer. This creates a leak if the string is heap-allocated.
185
185
 
186
- To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a disposable type with `koffi.dispose(name, type, func)`. This creates a type derived from another type, the only difference being that *func* gets called with the original pointer once the value has been converted and is not needed anymore.
186
+ To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a **disposable type** with `koffi.dispose(name, type, func)`. This creates a type derived from another type, the only difference being that *func* gets called with the original pointer once the value has been converted and is not needed anymore.
187
187
 
188
188
  The *name* can be omitted to create an anonymous disposable type. If *func* is omitted or is null, Koffi will use `koffi.free(ptr)` (which calls the standard C library *free* function under the hood).
189
189
 
@@ -199,7 +199,7 @@ The following example illustrates the use of a disposable type derived from *str
199
199
  const koffi = require('koffi');
200
200
  const lib = koffi.load('libc.so.6');
201
201
 
202
- // You can also use: const strdup = lib.func('const char *! asprintf(const char *str)')
202
+ // You can also use: const strdup = lib.func('const char *! strdup(const char *str)')
203
203
  const HeapStr = koffi.disposable('str');
204
204
  const strdup = lib.cdecl('strdup', HeapStr, ['str']);
205
205
 
@@ -207,7 +207,7 @@ let copy = strdup('Hello!');
207
207
  console.log(copy); // Prints Hello!
208
208
  ```
209
209
 
210
- When you declare functions with the [prototype-like syntax](#c-like-prototypes), you can either use named disposables types or use the '!' shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls `koffi.free(ptr)`.
210
+ When you declare functions with the [prototype-like syntax](#c-like-prototypes), you can either use named disposable types or use the '!' shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls `koffi.free(ptr)`.
211
211
 
212
212
  ```js
213
213
  const koffi = require('koffi');
@@ -515,7 +515,15 @@ Koffi can also convert JS strings to fixed-sized arrays in the following cases:
515
515
 
516
516
  The reverse case is also true, Koffi can convert a C fixed-size buffer to a JS string. This happens by default for char, char16 and char16_t arrays, but you can also explicitly ask for this with the `string` array hint (e.g. `koffi.array('char', 8, 'string')`).
517
517
 
518
- ## Type introspection
518
+ ## Disposable types
519
+
520
+ Disposable types allow you to register a function that will automatically called after each C to JS conversion performed by Koffi. This can be used to avoid leaking heap-allocated strings, for example.
521
+
522
+ Read the documentation for [disposable types](functions.md#heap-allocated-values) on the page about function calls.
523
+
524
+ ## Utility functions
525
+
526
+ ### Type introspection
519
527
 
520
528
  Koffi exposes three functions to explore type information:
521
529
 
@@ -540,6 +548,6 @@ console.log(koffi.sizeof('long'));
540
548
  console.log(koffi.sizeof(koffi.types.long));
541
549
  ```
542
550
 
543
- ## Type aliasing
551
+ ### Type aliases
544
552
 
545
553
  You can alias a type with `koffi.alias(name, type)`. Aliased types are completely equivalent.
@@ -172,6 +172,10 @@
172
172
  <li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
173
173
  </ul>
174
174
 
175
+ </div>
176
+ <div style="text-align: center; margin-top: 2em;">
177
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
178
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/NPM-2.0.0-brightgreen" alt="NPM"/></a>
175
179
  </div>
176
180
  </div>
177
181
 
@@ -215,8 +219,8 @@
215
219
  </ul>
216
220
  <table style="margin: 0 auto;">
217
221
  <tr>
218
- <td><a href="static/perf_linux_20220628.png" target="_blank"><img src="static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
219
- <td><a href="static/perf_windows_20220628.png" target="_blank"><img src="static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
222
+ <td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
223
+ <td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
220
224
  </tr>
221
225
  </table>
222
226
  <p>These results are detailed and explained below, and compared to node-ffi/node-ffi-napi.</p>
@@ -172,6 +172,10 @@
172
172
  <li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Changelog</a></li>
173
173
  </ul>
174
174
 
175
+ </div>
176
+ <div style="text-align: center; margin-top: 2em;">
177
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
178
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/NPM-2.0.0-brightgreen" alt="NPM"/></a>
175
179
  </div>
176
180
  </div>
177
181
 
@@ -211,8 +215,8 @@
211
215
  <h3>Koffi 2.0.0<a class="headerlink" href="#koffi-2-0-0" title="Permalink to this heading">#</a></h3>
212
216
  <p><strong>Major new features:</strong></p>
213
217
  <ul class="simple">
214
- <li><p>Add disposable types for automatic disposal of C values (such as heap-allocated strings)</p></li>
215
- <li><p>Add support for registered callbacks, that can be called after FFI call</p></li>
218
+ <li><p>Add <a class="reference internal" href="functions#heap-allocated-values"><span class="std std-doc">disposable types</span></a> for automatic disposal of C values (such as heap-allocated strings)</p></li>
219
+ <li><p>Add support for <a class="reference internal" href="functions#registered-callbacks"><span class="std std-doc">registered callbacks</span></a>, that can be called after the initial FFI call</p></li>
216
220
  <li><p>Support named pointer types</p></li>
217
221
  <li><p>Support complex type specifications outside of prototype parser</p></li>
218
222
  </ul>
@@ -474,10 +478,10 @@
474
478
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
475
479
  <span class="linenos"> 2</span>
476
480
  <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">FILE</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;FILE&#39;</span><span class="p">);</span>
477
- <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">fopen</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;FILE fopen(const char *path, const char *mode)&#39;</span><span class="p">);</span>
478
- <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">fclose</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int fclose(FILE stream)&#39;</span><span class="p">);</span>
481
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">fopen</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;fopen&#39;</span><span class="p">,</span> <span class="s1">&#39;FILE&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">]);</span>
482
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">fopen</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;fclose&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;FILE&#39;</span><span class="p">]);</span>
479
483
  <span class="linenos"> 6</span>
480
- <span class="linenos"> 7</span><span class="kd">let</span> <span class="nx">fp</span> <span class="o">=</span> <span class="nx">fopen</span><span class="p">(</span><span class="s1">&#39;touch&#39;</span><span class="p">,</span> <span class="s1">&#39;wb&#39;</span><span class="p">);</span>
484
+ <span class="linenos"> 7</span><span class="kd">let</span> <span class="nx">fp</span> <span class="o">=</span> <span class="nx">fopen</span><span class="p">(</span><span class="s1">&#39;EMPTY&#39;</span><span class="p">,</span> <span class="s1">&#39;wb&#39;</span><span class="p">);</span>
481
485
  <span class="linenos"> 8</span><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">fp</span><span class="p">)</span>
482
486
  <span class="linenos"> 9</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;Failed to open file&#39;</span><span class="p">);</span>
483
487
  <span class="linenos">10</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
@@ -486,10 +490,10 @@
486
490
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.x</span>
487
491
  <span class="linenos"> 2</span>
488
492
  <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">FILE</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;FILE&#39;</span><span class="p">);</span>
489
- <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">fopen</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;FILE *fopen(const char *path, const char *mode)&#39;</span><span class="p">);</span>
490
- <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">fclose</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int fclose(FILE *stream)&#39;</span><span class="p">);</span>
493
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">fopen</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;fopen&#39;</span><span class="p">,</span> <span class="s1">&#39;FILE *&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">]);</span>
494
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">fopen</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;fclose&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;FILE *&#39;</span><span class="p">]);</span>
491
495
  <span class="linenos"> 6</span>
492
- <span class="linenos"> 7</span><span class="kd">let</span> <span class="nx">fp</span> <span class="o">=</span> <span class="nx">fopen</span><span class="p">(</span><span class="s1">&#39;touch&#39;</span><span class="p">,</span> <span class="s1">&#39;wb&#39;</span><span class="p">);</span>
496
+ <span class="linenos"> 7</span><span class="kd">let</span> <span class="nx">fp</span> <span class="o">=</span> <span class="nx">fopen</span><span class="p">(</span><span class="s1">&#39;EMPTY&#39;</span><span class="p">,</span> <span class="s1">&#39;wb&#39;</span><span class="p">);</span>
493
497
  <span class="linenos"> 8</span><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">fp</span><span class="p">)</span>
494
498
  <span class="linenos"> 9</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;Failed to open file&#39;</span><span class="p">);</span>
495
499
  <span class="linenos">10</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
@@ -498,10 +502,10 @@
498
502
  <p>For functions that set opaque handles through output parameters (such as <code class="docutils literal notranslate"><span class="pre">sqlite3_open_v2</span></code>), you must now use a single element array as shown below:</p>
499
503
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
500
504
  <span class="linenos"> 2</span>
501
- <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">sqlite3_db</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;sqlite3_db&#39;</span><span class="p">);</span>
505
+ <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">sqlite3</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;sqlite3&#39;</span><span class="p">);</span>
502
506
  <span class="linenos"> 4</span>
503
- <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_open_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">out</span><span class="p">(</span><span class="nx">sqlite3_db</span><span class="p">),</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">]);</span>
504
- <span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_close_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="nx">sqlite3_db</span><span class="p">]);</span>
507
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int sqlite3_open_v2(const char *, _Out_ sqlite3 *db, int, const char *)&#39;</span><span class="p">);</span>
508
+ <span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int sqlite3_close_v2(sqlite3 db)&#39;</span><span class="p">);</span>
505
509
  <span class="linenos"> 7</span>
506
510
  <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">=</span> <span class="mh">0x2</span><span class="p">;</span>
507
511
  <span class="linenos"> 9</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_CREATE</span> <span class="o">=</span> <span class="mh">0x4</span><span class="p">;</span>
@@ -516,10 +520,10 @@
516
520
  </div>
517
521
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.x</span>
518
522
  <span class="linenos"> 2</span>
519
- <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">sqlite3_db</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;sqlite3_db&#39;</span><span class="p">);</span>
523
+ <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">sqlite3</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;sqlite3&#39;</span><span class="p">);</span>
520
524
  <span class="linenos"> 4</span>
521
- <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_open_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">out</span><span class="p">(</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3_db</span><span class="p">,</span> <span class="mf">2</span><span class="p">)),</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">]);</span>
522
- <span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_close_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3_db</span><span class="p">)]);</span>
525
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int sqlite3_open_v2(const char *, _Out_ sqlite3 **db, int, const char *)&#39;</span><span class="p">);</span>
526
+ <span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int sqlite3_close_v2(sqlite3 *db)&#39;</span><span class="p">);</span>
523
527
  <span class="linenos"> 7</span>
524
528
  <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">=</span> <span class="mh">0x2</span><span class="p">;</span>
525
529
  <span class="linenos"> 9</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_CREATE</span> <span class="o">=</span> <span class="mh">0x4</span><span class="p">;</span>
@@ -172,6 +172,10 @@
172
172
  <li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
173
173
  </ul>
174
174
 
175
+ </div>
176
+ <div style="text-align: center; margin-top: 2em;">
177
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
178
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/NPM-2.0.0-brightgreen" alt="NPM"/></a>
175
179
  </div>
176
180
  </div>
177
181
 
@@ -172,6 +172,10 @@
172
172
  <li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
173
173
  </ul>
174
174
 
175
+ </div>
176
+ <div style="text-align: center; margin-top: 2em;">
177
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
178
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/NPM-2.0.0-brightgreen" alt="NPM"/></a>
175
179
  </div>
176
180
  </div>
177
181
 
@@ -372,11 +376,11 @@
372
376
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
373
377
  <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;sqlite3.so&#39;</span><span class="p">);</span>
374
378
  <span class="linenos"> 3</span>
375
- <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">sqlite3_db</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;sqlite3_db&#39;</span><span class="p">);</span>
379
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">sqlite3</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="s1">&#39;sqlite3&#39;</span><span class="p">);</span>
376
380
  <span class="linenos"> 5</span>
377
381
  <span class="linenos"> 6</span><span class="c1">// Use koffi.out() on a double pointer to copy out (from C to JS) after the call</span>
378
- <span class="linenos"> 7</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_open_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">out</span><span class="p">(</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3_db</span><span class="p">,</span> <span class="mf">2</span><span class="p">)),</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">]);</span>
379
- <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_close_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3_db</span><span class="p">)]);</span>
382
+ <span class="linenos"> 7</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_open_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">out</span><span class="p">(</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3</span><span class="p">,</span> <span class="mf">2</span><span class="p">)),</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">]);</span>
383
+ <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_close_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3</span><span class="p">)]);</span>
380
384
  <span class="linenos"> 9</span>
381
385
  <span class="linenos">10</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">=</span> <span class="mh">0x2</span><span class="p">;</span>
382
386
  <span class="linenos">11</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_CREATE</span> <span class="o">=</span> <span class="mh">0x4</span><span class="p">;</span>
@@ -395,7 +399,7 @@
395
399
  <h3>Heap-allocated values<a class="headerlink" href="#heap-allocated-values" title="Permalink to this heading">#</a></h3>
396
400
  <p>Some C functions return heap-allocated values directly or through output parameters. While Koffi automatically converts values from C to JS (to a string or an object), it does not know when something needs to be freed, or how.</p>
397
401
  <p>For opaque handles, such as FILE, this does not matter because you will explicitly call <code class="docutils literal notranslate"><span class="pre">fclose()</span></code> on them. But some values (such as strings) get implicitly converted by Koffi, and you lose access to the original pointer. This creates a leak if the string is heap-allocated.</p>
398
- <p>To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a disposable type with <code class="docutils literal notranslate"><span class="pre">koffi.dispose(name,</span> <span class="pre">type,</span> <span class="pre">func)</span></code>. This creates a type derived from another type, the only difference being that <em>func</em> gets called with the original pointer once the value has been converted and is not needed anymore.</p>
402
+ <p>To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a <strong>disposable type</strong> with <code class="docutils literal notranslate"><span class="pre">koffi.dispose(name,</span> <span class="pre">type,</span> <span class="pre">func)</span></code>. This creates a type derived from another type, the only difference being that <em>func</em> gets called with the original pointer once the value has been converted and is not needed anymore.</p>
399
403
  <p>The <em>name</em> can be omitted to create an anonymous disposable type. If <em>func</em> is omitted or is null, Koffi will use <code class="docutils literal notranslate"><span class="pre">koffi.free(ptr)</span></code> (which calls the standard C library <em>free</em> function under the hood).</p>
400
404
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">AnonHeapStr</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">&#39;str&#39;</span><span class="p">);</span> <span class="c1">// Anonymous type (cannot be used in function prototypes)</span>
401
405
  <span class="linenos">2</span><span class="kd">const</span> <span class="nx">NamedHeapStr</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">&#39;HeapStr&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">);</span> <span class="c1">// Same thing, but named so usable in function prototypes</span>
@@ -406,7 +410,7 @@
406
410
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
407
411
  <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;libc.so.6&#39;</span><span class="p">);</span>
408
412
  <span class="linenos">3</span>
409
- <span class="linenos">4</span><span class="c1">// You can also use: const strdup = lib.func(&#39;const char *! asprintf(const char *str)&#39;)</span>
413
+ <span class="linenos">4</span><span class="c1">// You can also use: const strdup = lib.func(&#39;const char *! strdup(const char *str)&#39;)</span>
410
414
  <span class="linenos">5</span><span class="kd">const</span> <span class="nx">HeapStr</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">&#39;str&#39;</span><span class="p">);</span>
411
415
  <span class="linenos">6</span><span class="kd">const</span> <span class="nx">strdup</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">cdecl</span><span class="p">(</span><span class="s1">&#39;strdup&#39;</span><span class="p">,</span> <span class="nx">HeapStr</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">]);</span>
412
416
  <span class="linenos">7</span>
@@ -414,7 +418,7 @@
414
418
  <span class="linenos">9</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">copy</span><span class="p">);</span> <span class="c1">// Prints Hello!</span>
415
419
  </pre></div>
416
420
  </div>
417
- <p>When you declare functions with the <a class="reference internal" href="#c-like-prototypes"><span class="std std-doc">prototype-like syntax</span></a>, you can either use named disposables types or use the ‘!’ shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls <code class="docutils literal notranslate"><span class="pre">koffi.free(ptr)</span></code>.</p>
421
+ <p>When you declare functions with the <a class="reference internal" href="#c-like-prototypes"><span class="std std-doc">prototype-like syntax</span></a>, you can either use named disposable types or use the ‘!’ shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls <code class="docutils literal notranslate"><span class="pre">koffi.free(ptr)</span></code>.</p>
418
422
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
419
423
  <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;libc.so.6&#39;</span><span class="p">);</span>
420
424
  <span class="linenos">3</span>
@@ -170,6 +170,10 @@
170
170
  <li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
171
171
  </ul>
172
172
 
173
+ </div>
174
+ <div style="text-align: center; margin-top: 2em;">
175
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
176
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/NPM-2.0.0-brightgreen" alt="NPM"/></a>
173
177
  </div>
174
178
  </div>
175
179