koffi 1.3.11 → 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 (94) hide show
  1. package/CMakeLists.txt +7 -2
  2. package/ChangeLog.md +53 -15
  3. package/README.md +6 -0
  4. package/build/qemu/2.0.1/koffi_darwin_arm64.tar.gz +0 -0
  5. package/build/qemu/2.0.1/koffi_darwin_x64.tar.gz +0 -0
  6. package/build/qemu/2.0.1/koffi_freebsd_arm64.tar.gz +0 -0
  7. package/build/qemu/2.0.1/koffi_freebsd_ia32.tar.gz +0 -0
  8. package/build/qemu/2.0.1/koffi_freebsd_x64.tar.gz +0 -0
  9. package/build/qemu/2.0.1/koffi_linux_arm32hf.tar.gz +0 -0
  10. package/build/qemu/2.0.1/koffi_linux_arm64.tar.gz +0 -0
  11. package/build/qemu/2.0.1/koffi_linux_ia32.tar.gz +0 -0
  12. package/build/qemu/2.0.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  13. package/build/qemu/2.0.1/koffi_linux_x64.tar.gz +0 -0
  14. package/build/qemu/2.0.1/koffi_openbsd_ia32.tar.gz +0 -0
  15. package/build/qemu/2.0.1/koffi_openbsd_x64.tar.gz +0 -0
  16. package/build/qemu/2.0.1/koffi_win32_arm64.tar.gz +0 -0
  17. package/build/qemu/2.0.1/koffi_win32_ia32.tar.gz +0 -0
  18. package/build/qemu/2.0.1/koffi_win32_x64.tar.gz +0 -0
  19. package/doc/changes.md +156 -1
  20. package/doc/conf.py +14 -1
  21. package/doc/contribute.md +0 -1
  22. package/doc/dist/doctrees/benchmarks.doctree +0 -0
  23. package/doc/dist/doctrees/changes.doctree +0 -0
  24. package/doc/dist/doctrees/environment.pickle +0 -0
  25. package/doc/dist/doctrees/functions.doctree +0 -0
  26. package/doc/dist/doctrees/index.doctree +0 -0
  27. package/doc/dist/doctrees/types.doctree +0 -0
  28. package/doc/dist/html/.buildinfo +1 -1
  29. package/doc/dist/html/_sources/benchmarks.md.txt +2 -2
  30. package/doc/dist/html/_sources/changes.md.txt +156 -1
  31. package/doc/dist/html/_sources/functions.md.txt +14 -10
  32. package/doc/dist/html/_sources/types.md.txt +18 -1
  33. package/doc/dist/html/benchmarks.html +7 -3
  34. package/doc/dist/html/changes.html +230 -14
  35. package/doc/dist/html/contribute.html +5 -1
  36. package/doc/dist/html/functions.html +25 -18
  37. package/doc/dist/html/genindex.html +5 -1
  38. package/doc/dist/html/index.html +13 -19
  39. package/doc/dist/html/memory.html +7 -3
  40. package/doc/dist/html/objects.inv +0 -0
  41. package/doc/dist/html/platforms.html +6 -2
  42. package/doc/dist/html/search.html +5 -1
  43. package/doc/dist/html/searchindex.js +1 -1
  44. package/doc/dist/html/start.html +5 -1
  45. package/doc/dist/html/types.html +28 -4
  46. package/doc/functions.md +138 -14
  47. package/doc/templates/badges.html +5 -0
  48. package/doc/types.md +45 -12
  49. package/package.json +9 -7
  50. package/qemu/registry/machines.json +5 -5
  51. package/qemu/registry/sha256sum.txt +16 -16
  52. package/src/abi_arm32.cc +91 -19
  53. package/src/abi_arm32_fwd.S +121 -57
  54. package/src/abi_arm64.cc +91 -19
  55. package/src/abi_arm64_fwd.S +96 -0
  56. package/src/abi_arm64_fwd.asm +128 -0
  57. package/src/abi_riscv64.cc +89 -19
  58. package/src/abi_riscv64_fwd.S +96 -0
  59. package/src/abi_x64_sysv.cc +94 -22
  60. package/src/abi_x64_sysv_fwd.S +96 -0
  61. package/src/abi_x64_win.cc +89 -19
  62. package/src/abi_x64_win_fwd.asm +128 -0
  63. package/src/abi_x86.cc +94 -19
  64. package/src/abi_x86_fwd.S +96 -0
  65. package/src/abi_x86_fwd.asm +128 -0
  66. package/src/call.cc +97 -63
  67. package/src/call.hh +2 -1
  68. package/src/ffi.cc +453 -141
  69. package/src/ffi.hh +23 -9
  70. package/src/parser.cc +18 -41
  71. package/src/util.cc +117 -27
  72. package/src/util.hh +3 -2
  73. package/test/callbacks.js +54 -8
  74. package/test/misc.c +29 -14
  75. package/test/raylib.js +1 -1
  76. package/test/sqlite.js +25 -17
  77. package/test/sync.js +44 -32
  78. package/vendor/libcc/libcc.cc +18 -5
  79. package/vendor/libcc/libcc.hh +70 -23
  80. package/build/qemu/1.3.11/koffi_darwin_arm64.tar.gz +0 -0
  81. package/build/qemu/1.3.11/koffi_darwin_x64.tar.gz +0 -0
  82. package/build/qemu/1.3.11/koffi_freebsd_arm64.tar.gz +0 -0
  83. package/build/qemu/1.3.11/koffi_freebsd_ia32.tar.gz +0 -0
  84. package/build/qemu/1.3.11/koffi_freebsd_x64.tar.gz +0 -0
  85. package/build/qemu/1.3.11/koffi_linux_arm32hf.tar.gz +0 -0
  86. package/build/qemu/1.3.11/koffi_linux_arm64.tar.gz +0 -0
  87. package/build/qemu/1.3.11/koffi_linux_ia32.tar.gz +0 -0
  88. package/build/qemu/1.3.11/koffi_linux_riscv64hf64.tar.gz +0 -0
  89. package/build/qemu/1.3.11/koffi_linux_x64.tar.gz +0 -0
  90. package/build/qemu/1.3.11/koffi_openbsd_ia32.tar.gz +0 -0
  91. package/build/qemu/1.3.11/koffi_openbsd_x64.tar.gz +0 -0
  92. package/build/qemu/1.3.11/koffi_win32_arm64.tar.gz +0 -0
  93. package/build/qemu/1.3.11/koffi_win32_ia32.tar.gz +0 -0
  94. package/build/qemu/1.3.11/koffi_win32_x64.tar.gz +0 -0
@@ -1,4 +1,4 @@
1
- # Function calls
1
+ # Functions
2
2
 
3
3
  ## Function definitions
4
4
 
@@ -158,20 +158,22 @@ This example opens an in-memory SQLite database, and uses the node-ffi-style fun
158
158
 
159
159
  ```js
160
160
  const koffi = require('koffi');
161
- const lib = koffi.load('sqlite.so');
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;
171
171
 
172
- let db = {};
173
- if (sqlite3_open_v2(':memory:', db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
172
+ let out = [null];
173
+ if (sqlite3_open_v2(':memory:', out, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
174
174
  throw new Error('Failed to open database');
175
+ let db = out[0];
176
+
175
177
  sqlite3_close_v2(db);
176
178
  ```
177
179
 
@@ -181,7 +183,7 @@ Some C functions return heap-allocated values directly or through output paramet
181
183
 
182
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.
183
185
 
184
- 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.
185
187
 
186
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).
187
189
 
@@ -197,7 +199,7 @@ The following example illustrates the use of a disposable type derived from *str
197
199
  const koffi = require('koffi');
198
200
  const lib = koffi.load('libc.so.6');
199
201
 
200
- // 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)')
201
203
  const HeapStr = koffi.disposable('str');
202
204
  const strdup = lib.cdecl('strdup', HeapStr, ['str']);
203
205
 
@@ -205,7 +207,7 @@ let copy = strdup('Hello!');
205
207
  console.log(copy); // Prints Hello!
206
208
  ```
207
209
 
208
- 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)`.
209
211
 
210
212
  ```js
211
213
  const koffi = require('koffi');
@@ -246,6 +248,8 @@ Callbacks **have changed in version 2.0**.
246
248
  In Koffi 1.x, callbacks were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer.
247
249
 
248
250
  Now, you must use them through a pointer: `void CallIt(CallbackType func)` in Koffi 1.x becomes `void CallIt(CallbackType *func)` in version 2.0 and newer.
251
+
252
+ Consult the [migration guide](changes.md) for more information.
249
253
  ```
250
254
 
251
255
  Koffi only uses predefined static trampolines, and does not need to generate code at runtime, which makes it compatible with platforms with hardened W^X migitations (such as PaX mprotect). However, this imposes some restrictions on the maximum number of callbacks, and their duration.
@@ -154,6 +154,8 @@ Opaque handles **have changed in version 2.0**.
154
154
  In Koffi 1.x, opaque handles were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer.
155
155
 
156
156
  Now, you must use them through a pointer, and use an array for output parameters. This is shown in the example below (look for the call to `ConcatNewOut` in the JS part), and is described in the section on [output parameters](functions.md#output-parameters).
157
+
158
+ Consult the [migration guide](changes.md) for more information.
157
159
  ```
158
160
 
159
161
  The full example below implements an iterative string builder (concatenator) in C, and uses it from Javascript to output a mix of Hello World and FizzBuzz. The builder is hidden behind an opaque handle, and is created and destroyed using a pair of C functions: `ConcatNew` (or `ConcatNewOut`) and `ConcatFree`.
@@ -513,18 +515,29 @@ Koffi can also convert JS strings to fixed-sized arrays in the following cases:
513
515
 
514
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')`).
515
517
 
516
- ## 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
517
527
 
518
528
  Koffi exposes three functions to explore type information:
519
529
 
520
530
  - `koffi.sizeof(type)` to get the size of a type
521
531
  - `koffi.alignof(type)` to get the alignment of a type
522
532
  - `koffi.introspect(type)` to get the definition of a type in an object containing: name, primitive, size, alignment, members (structs), reference (array, pointer) and length (array)
533
+ - `koffi.resolve(type)` to get the resolved type object from a type string
523
534
 
524
535
  ```{note}
525
536
  The value returned by `introspect()` has **changed in version 2.0**.
526
537
 
527
538
  In Koffi 1.x, it could only be used with struct types and returned the object passed to koffi.struct() with the member names and types.
539
+
540
+ Consult the [migration guide](changes.md) for more information.
528
541
  ```
529
542
 
530
543
  Just like before, you can refer to primitive types by their name or through `koffi.types`:
@@ -534,3 +547,7 @@ Just like before, you can refer to primitive types by their name or through `kof
534
547
  console.log(koffi.sizeof('long'));
535
548
  console.log(koffi.sizeof(koffi.types.long));
536
549
  ```
550
+
551
+ ### Type aliases
552
+
553
+ You can alias a type with `koffi.alias(name, type)`. Aliased types are completely equivalent.
@@ -165,13 +165,17 @@
165
165
  <li class="toctree-l1"><a class="reference internal" href="platforms">Requirements</a></li>
166
166
  <li class="toctree-l1"><a class="reference internal" href="start">Quick start</a></li>
167
167
  <li class="toctree-l1"><a class="reference internal" href="types">Data types</a></li>
168
- <li class="toctree-l1"><a class="reference internal" href="functions">Function calls</a></li>
168
+ <li class="toctree-l1"><a class="reference internal" href="functions">Functions</a></li>
169
169
  <li class="toctree-l1"><a class="reference internal" href="memory">Memory usage</a></li>
170
170
  <li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Benchmarks</a></li>
171
171
  <li class="toctree-l1"><a class="reference internal" href="contribute">Contributing</a></li>
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>
@@ -165,13 +165,17 @@
165
165
  <li class="toctree-l1"><a class="reference internal" href="platforms">Requirements</a></li>
166
166
  <li class="toctree-l1"><a class="reference internal" href="start">Quick start</a></li>
167
167
  <li class="toctree-l1"><a class="reference internal" href="types">Data types</a></li>
168
- <li class="toctree-l1"><a class="reference internal" href="functions">Function calls</a></li>
168
+ <li class="toctree-l1"><a class="reference internal" href="functions">Functions</a></li>
169
169
  <li class="toctree-l1"><a class="reference internal" href="memory">Memory usage</a></li>
170
170
  <li class="toctree-l1"><a class="reference internal" href="benchmarks">Benchmarks</a></li>
171
171
  <li class="toctree-l1"><a class="reference internal" href="contribute">Contributing</a></li>
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
 
@@ -205,15 +209,68 @@
205
209
  <article role="main">
206
210
  <section id="changelog">
207
211
  <h1>Changelog<a class="headerlink" href="#changelog" title="Permalink to this heading">#</a></h1>
212
+ <section id="history">
213
+ <h2>History<a class="headerlink" href="#history" title="Permalink to this heading">#</a></h2>
214
+ <section id="koffi-2-0-0">
215
+ <h3>Koffi 2.0.0<a class="headerlink" href="#koffi-2-0-0" title="Permalink to this heading">#</a></h3>
216
+ <p><strong>Major new features:</strong></p>
217
+ <ul class="simple">
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>
220
+ <li><p>Support named pointer types</p></li>
221
+ <li><p>Support complex type specifications outside of prototype parser</p></li>
222
+ </ul>
223
+ <p><strong>Minor new features:</strong></p>
224
+ <ul class="simple">
225
+ <li><p>Support type aliases with <code class="docutils literal notranslate"><span class="pre">koffi.alias()</span></code></p></li>
226
+ <li><p>Add <code class="docutils literal notranslate"><span class="pre">koffi.resolve()</span></code> to resolve type strings</p></li>
227
+ <li><p>Expose all primitive type aliases in <code class="docutils literal notranslate"><span class="pre">koffi.types</span></code></p></li>
228
+ <li><p>Correctly pass exceptions thrown in JS callbacks</p></li>
229
+ </ul>
230
+ <p><strong>Breaking API changes:</strong></p>
231
+ <ul class="simple">
232
+ <li><p>Change handling of callback types, which must be used through pointers</p></li>
233
+ <li><p>Change handling of opaque handles, which must be used through pointers</p></li>
234
+ <li><p>Support all types in <code class="docutils literal notranslate"><span class="pre">koffi.introspect(type)</span></code></p></li>
235
+ </ul>
236
+ <p>Consult the <a class="reference internal" href="#migration-guide"><span class="std std-doc">migration guide</span></a> for more information.</p>
237
+ </section>
238
+ <section id="koffi-1-3-12">
239
+ <h3>Koffi 1.3.12<a class="headerlink" href="#koffi-1-3-12" title="Permalink to this heading">#</a></h3>
240
+ <p><strong>Main fixes:</strong></p>
241
+ <ul class="simple">
242
+ <li><p>Fix support for Yarn package manager</p></li>
243
+ </ul>
244
+ </section>
245
+ <section id="koffi-1-3-11">
246
+ <h3>Koffi 1.3.11<a class="headerlink" href="#koffi-1-3-11" title="Permalink to this heading">#</a></h3>
247
+ <p><strong>Main fixes:</strong></p>
248
+ <ul class="simple">
249
+ <li><p>Fix broken parsing of <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*</span></code> when used for first parameter</p></li>
250
+ </ul>
251
+ </section>
252
+ <section id="koffi-1-3-10">
253
+ <h3>Koffi 1.3.10<a class="headerlink" href="#koffi-1-3-10" title="Permalink to this heading">#</a></h3>
254
+ <p><strong>Main fixes:</strong></p>
255
+ <ul class="simple">
256
+ <li><p>Fix support for callbacks with more than 4 parameters on Windows x64</p></li>
257
+ <li><p>Fix support for callbacks with multiple floating-point arguments on ARM32 platforms</p></li>
258
+ <li><p>Fix possibly incorrect conversion for uint32_t callback parameters</p></li>
259
+ </ul>
260
+ <p><strong>Other changes:</strong></p>
261
+ <ul class="simple">
262
+ <li><p>Various documentation fixes and improvements</p></li>
263
+ </ul>
264
+ </section>
208
265
  <section id="koffi-1-3-9">
209
- <h2>Koffi 1.3.9<a class="headerlink" href="#koffi-1-3-9" title="Permalink to this heading">#</a></h2>
266
+ <h3>Koffi 1.3.9<a class="headerlink" href="#koffi-1-3-9" title="Permalink to this heading">#</a></h3>
210
267
  <p><strong>Main fixes:</strong></p>
211
268
  <ul class="simple">
212
269
  <li><p>Fix prebuild compatibility with Electron on Windows x64</p></li>
213
270
  </ul>
214
271
  </section>
215
272
  <section id="koffi-1-3-8">
216
- <h2>Koffi 1.3.8<a class="headerlink" href="#koffi-1-3-8" title="Permalink to this heading">#</a></h2>
273
+ <h3>Koffi 1.3.8<a class="headerlink" href="#koffi-1-3-8" title="Permalink to this heading">#</a></h3>
217
274
  <p><strong>Main changes:</strong></p>
218
275
  <ul class="simple">
219
276
  <li><p>Prevent callback reuse beyond FFI call</p></li>
@@ -225,7 +282,7 @@
225
282
  </ul>
226
283
  </section>
227
284
  <section id="koffi-1-3-7">
228
- <h2>Koffi 1.3.7<a class="headerlink" href="#koffi-1-3-7" title="Permalink to this heading">#</a></h2>
285
+ <h3>Koffi 1.3.7<a class="headerlink" href="#koffi-1-3-7" title="Permalink to this heading">#</a></h3>
229
286
  <p><strong>Main fixes:</strong></p>
230
287
  <ul class="simple">
231
288
  <li><p>Fix crash when using callbacks inside structs</p></li>
@@ -239,7 +296,7 @@
239
296
  </ul>
240
297
  </section>
241
298
  <section id="koffi-1-3-6">
242
- <h2>Koffi 1.3.6<a class="headerlink" href="#koffi-1-3-6" title="Permalink to this heading">#</a></h2>
299
+ <h3>Koffi 1.3.6<a class="headerlink" href="#koffi-1-3-6" title="Permalink to this heading">#</a></h3>
243
300
  <p><strong>Main fixes:</strong></p>
244
301
  <ul class="simple">
245
302
  <li><p>Fix install error with Node &lt; 15 on Windows (build system bug)</p></li>
@@ -252,7 +309,7 @@
252
309
  </ul>
253
310
  </section>
254
311
  <section id="koffi-1-3-5">
255
- <h2>Koffi 1.3.5<a class="headerlink" href="#koffi-1-3-5" title="Permalink to this heading">#</a></h2>
312
+ <h3>Koffi 1.3.5<a class="headerlink" href="#koffi-1-3-5" title="Permalink to this heading">#</a></h3>
256
313
  <p><strong>Main changes:</strong></p>
257
314
  <ul class="simple">
258
315
  <li><p>Fix memory leak when many async calls are running</p></li>
@@ -265,14 +322,14 @@
265
322
  </ul>
266
323
  </section>
267
324
  <section id="koffi-1-3-4">
268
- <h2>Koffi 1.3.4<a class="headerlink" href="#koffi-1-3-4" title="Permalink to this heading">#</a></h2>
325
+ <h3>Koffi 1.3.4<a class="headerlink" href="#koffi-1-3-4" title="Permalink to this heading">#</a></h3>
269
326
  <p><strong>Main fixes:</strong></p>
270
327
  <ul class="simple">
271
328
  <li><p>Fix possible OpenBSD i386 crash with <code class="docutils literal notranslate"><span class="pre">(void)</span></code> functions</p></li>
272
329
  </ul>
273
330
  </section>
274
331
  <section id="koffi-1-3-3">
275
- <h2>Koffi 1.3.3<a class="headerlink" href="#koffi-1-3-3" title="Permalink to this heading">#</a></h2>
332
+ <h3>Koffi 1.3.3<a class="headerlink" href="#koffi-1-3-3" title="Permalink to this heading">#</a></h3>
276
333
  <p><strong>Main fixes:</strong></p>
277
334
  <ul class="simple">
278
335
  <li><p>Fix misconversion of signed integer return value as unsigned</p></li>
@@ -285,7 +342,7 @@
285
342
  </ul>
286
343
  </section>
287
344
  <section id="koffi-1-3-2">
288
- <h2>Koffi 1.3.2<a class="headerlink" href="#koffi-1-3-2" title="Permalink to this heading">#</a></h2>
345
+ <h3>Koffi 1.3.2<a class="headerlink" href="#koffi-1-3-2" title="Permalink to this heading">#</a></h3>
289
346
  <p><strong>Main fixes:</strong></p>
290
347
  <ul class="simple">
291
348
  <li><p>Support compilation in C++14 mode (graceful degradation)</p></li>
@@ -293,14 +350,14 @@
293
350
  </ul>
294
351
  </section>
295
352
  <section id="koffi-1-3-1">
296
- <h2>Koffi 1.3.1<a class="headerlink" href="#koffi-1-3-1" title="Permalink to this heading">#</a></h2>
353
+ <h3>Koffi 1.3.1<a class="headerlink" href="#koffi-1-3-1" title="Permalink to this heading">#</a></h3>
297
354
  <p><strong>Main fixes:</strong></p>
298
355
  <ul class="simple">
299
356
  <li><p>The prebuilt binary is tested when Koffi is installed, and a rebuild happens if it fails to load</p></li>
300
357
  </ul>
301
358
  </section>
302
359
  <section id="koffi-1-3-0">
303
- <h2>Koffi 1.3.0<a class="headerlink" href="#koffi-1-3-0" title="Permalink to this heading">#</a></h2>
360
+ <h3>Koffi 1.3.0<a class="headerlink" href="#koffi-1-3-0" title="Permalink to this heading">#</a></h3>
304
361
  <p><strong>Major changes:</strong></p>
305
362
  <ul class="simple">
306
363
  <li><p>Expand and move documentation to <a class="reference external" href="https://koffi.dev/">https://koffi.dev/</a></p></li>
@@ -317,21 +374,21 @@
317
374
  </ul>
318
375
  </section>
319
376
  <section id="koffi-1-2-4">
320
- <h2>Koffi 1.2.4<a class="headerlink" href="#koffi-1-2-4" title="Permalink to this heading">#</a></h2>
377
+ <h3>Koffi 1.2.4<a class="headerlink" href="#koffi-1-2-4" title="Permalink to this heading">#</a></h3>
321
378
  <p><strong>New features:</strong></p>
322
379
  <ul class="simple">
323
380
  <li><p>Windows ARM64 is now supported</p></li>
324
381
  </ul>
325
382
  </section>
326
383
  <section id="koffi-1-2-3">
327
- <h2>Koffi 1.2.3<a class="headerlink" href="#koffi-1-2-3" title="Permalink to this heading">#</a></h2>
384
+ <h3>Koffi 1.2.3<a class="headerlink" href="#koffi-1-2-3" title="Permalink to this heading">#</a></h3>
328
385
  <p><strong>New features:</strong></p>
329
386
  <ul class="simple">
330
387
  <li><p>A prebuilt binary for macOS ARM64 (M1) is now included</p></li>
331
388
  </ul>
332
389
  </section>
333
390
  <section id="koffi-1-2-1">
334
- <h2>Koffi 1.2.1<a class="headerlink" href="#koffi-1-2-1" title="Permalink to this heading">#</a></h2>
391
+ <h3>Koffi 1.2.1<a class="headerlink" href="#koffi-1-2-1" title="Permalink to this heading">#</a></h3>
335
392
  <p>This entry documents changes since version 1.1.0.</p>
336
393
  <p><strong>New features:</strong></p>
337
394
  <ul class="simple">
@@ -355,6 +412,149 @@
355
412
  <li><p>Use slower allocation for big objects instead of failing</p></li>
356
413
  </ul>
357
414
  </section>
415
+ </section>
416
+ <section id="migration-guide">
417
+ <h2>Migration guide<a class="headerlink" href="#migration-guide" title="Permalink to this heading">#</a></h2>
418
+ <section id="koffi-1-x-to-2-x">
419
+ <h3>Koffi 1.x to 2.x<a class="headerlink" href="#koffi-1-x-to-2-x" title="Permalink to this heading">#</a></h3>
420
+ <p>The API was changed in 2.x in a few ways, in order to reduce some excessively “magic” behavior and reduce the syntax differences between C and the C-like prototypes.</p>
421
+ <p>You may need to change your code if you use:</p>
422
+ <ul class="simple">
423
+ <li><p>Callback functions</p></li>
424
+ <li><p>Opaque handles</p></li>
425
+ <li><p><code class="docutils literal notranslate"><span class="pre">koffi.introspect()</span></code></p></li>
426
+ </ul>
427
+ <section id="callback-types">
428
+ <h4>Callback types<a class="headerlink" href="#callback-types" title="Permalink to this heading">#</a></h4>
429
+ <p>In Koffi 1.x, callbacks were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer. Now, you must use them through a pointer: <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">CallIt(CallbackType</span> <span class="pre">func)</span></code> in Koffi 1.x becomes <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">CallIt(CallbackType</span> <span class="pre">*func)</span></code> in version 2.0 and newer.</p>
430
+ <p>Given the following C code:</p>
431
+ <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
432
+ <span class="linenos">2</span>
433
+ <span class="linenos">3</span><span class="kt">int</span><span class="w"> </span><span class="nf">TransferToJS</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">age</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">cb</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">str</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">age</span><span class="p">))</span><span class="w"></span>
434
+ <span class="linenos">4</span><span class="p">{</span><span class="w"></span>
435
+ <span class="linenos">5</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">buf</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span><span class="w"></span>
436
+ <span class="linenos">6</span><span class="w"> </span><span class="n">snprintf</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">),</span><span class="w"> </span><span class="s">&quot;Hello %s!&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">str</span><span class="p">);</span><span class="w"></span>
437
+ <span class="linenos">7</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">cb</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="n">age</span><span class="p">);</span><span class="w"></span>
438
+ <span class="linenos">8</span><span class="p">}</span><span class="w"></span>
439
+ </pre></div>
440
+ </div>
441
+ <p>The two versions below illustrate the API difference between Koffi 1.x and Koffi 2.x:</p>
442
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
443
+ <span class="linenos"> 2</span>
444
+ <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">TransferCallback</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">callback</span><span class="p">(</span><span class="s1">&#39;int TransferCallback(const char *str, int age)&#39;</span><span class="p">);</span>
445
+ <span class="linenos"> 4</span>
446
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">TransferToJS</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;TransferToJS&#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="s1">&#39;int&#39;</span><span class="p">,</span> <span class="nx">TransferCallback</span><span class="p">]);</span>
447
+ <span class="linenos"> 6</span><span class="c1">// Equivalent to: const TransferToJS = lib.func(&#39;int TransferToJS(str s, int x, TransferCallback cb)&#39;);</span>
448
+ <span class="linenos"> 7</span>
449
+ <span class="linenos"> 8</span><span class="kd">let</span> <span class="nx">ret</span> <span class="o">=</span> <span class="nx">TransferToJS</span><span class="p">(</span><span class="s1">&#39;Niels&#39;</span><span class="p">,</span> <span class="mf">27</span><span class="p">,</span> <span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
450
+ <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">str</span><span class="p">);</span>
451
+ <span class="linenos">10</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Your age is:&#39;</span><span class="p">,</span> <span class="nx">age</span><span class="p">);</span>
452
+ <span class="linenos">11</span> <span class="k">return</span> <span class="mf">42</span><span class="p">;</span>
453
+ <span class="linenos">12</span><span class="p">});</span>
454
+ <span class="linenos">13</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">ret</span><span class="p">);</span>
455
+ </pre></div>
456
+ </div>
457
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.x</span>
458
+ <span class="linenos"> 2</span>
459
+ <span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">TransferCallback</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">callback</span><span class="p">(</span><span class="s1">&#39;int TransferCallback(const char *str, int age)&#39;</span><span class="p">);</span>
460
+ <span class="linenos"> 4</span>
461
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">TransferToJS</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;TransferToJS&#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="s1">&#39;int&#39;</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">TransferCallback</span><span class="p">)]);</span>
462
+ <span class="linenos"> 6</span><span class="c1">// Equivalent to: const TransferToJS = lib.func(&#39;int TransferToJS(str s, int x, TransferCallback *cb)&#39;);</span>
463
+ <span class="linenos"> 7</span>
464
+ <span class="linenos"> 8</span><span class="kd">let</span> <span class="nx">ret</span> <span class="o">=</span> <span class="nx">TransferToJS</span><span class="p">(</span><span class="s1">&#39;Niels&#39;</span><span class="p">,</span> <span class="mf">27</span><span class="p">,</span> <span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
465
+ <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">str</span><span class="p">);</span>
466
+ <span class="linenos">10</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Your age is:&#39;</span><span class="p">,</span> <span class="nx">age</span><span class="p">);</span>
467
+ <span class="linenos">11</span> <span class="k">return</span> <span class="mf">42</span><span class="p">;</span>
468
+ <span class="linenos">12</span><span class="p">});</span>
469
+ <span class="linenos">13</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">ret</span><span class="p">);</span>
470
+ </pre></div>
471
+ </div>
472
+ <p>Koffi 1.x only supported <a class="reference internal" href="functions#javascript-callbacks"><span class="std std-doc">transient callbacks</span></a>, you must use Koffi 2.x for registered callbacks.</p>
473
+ </section>
474
+ <section id="opaque-handles">
475
+ <h4>Opaque handles<a class="headerlink" href="#opaque-handles" title="Permalink to this heading">#</a></h4>
476
+ <p>In Koffi 1.x, opaque handles were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer. Now, you must use them through a pointer, and use an array for output parameters.</p>
477
+ <p>For functions that return handles or pass them by parameter:</p>
478
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
479
+ <span class="linenos"> 2</span>
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>
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>
483
+ <span class="linenos"> 6</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>
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>
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>
487
+ <span class="linenos">10</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
488
+ </pre></div>
489
+ </div>
490
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.x</span>
491
+ <span class="linenos"> 2</span>
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>
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>
495
+ <span class="linenos"> 6</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>
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>
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>
499
+ <span class="linenos">10</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
500
+ </pre></div>
501
+ </div>
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>
503
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
504
+ <span class="linenos"> 2</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>
506
+ <span class="linenos"> 4</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>
509
+ <span class="linenos"> 7</span>
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>
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>
512
+ <span class="linenos">10</span>
513
+ <span class="linenos">11</span><span class="kd">let</span> <span class="nx">db</span> <span class="o">=</span> <span class="p">{};</span>
514
+ <span class="linenos">12</span>
515
+ <span class="linenos">13</span><span class="k">if</span> <span class="p">(</span><span class="nx">sqlite3_open_v2</span><span class="p">(</span><span class="s1">&#39;:memory:&#39;</span><span class="p">,</span> <span class="nx">db</span><span class="p">,</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">|</span> <span class="nx">SQLITE_OPEN_CREATE</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span> <span class="o">!=</span> <span class="mf">0</span><span class="p">)</span>
516
+ <span class="linenos">14</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 database&#39;</span><span class="p">);</span>
517
+ <span class="linenos">15</span>
518
+ <span class="linenos">16</span><span class="nx">sqlite3_close_v2</span><span class="p">(</span><span class="nx">db</span><span class="p">);</span>
519
+ </pre></div>
520
+ </div>
521
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.x</span>
522
+ <span class="linenos"> 2</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>
524
+ <span class="linenos"> 4</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>
527
+ <span class="linenos"> 7</span>
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>
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>
530
+ <span class="linenos">10</span>
531
+ <span class="linenos">11</span><span class="kd">let</span> <span class="nx">db</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
532
+ <span class="linenos">12</span>
533
+ <span class="linenos">13</span><span class="kd">let</span> <span class="nx">ptr</span> <span class="o">=</span> <span class="p">[</span><span class="kc">null</span><span class="p">];</span>
534
+ <span class="linenos">14</span><span class="k">if</span> <span class="p">(</span><span class="nx">sqlite3_open_v2</span><span class="p">(</span><span class="s1">&#39;:memory:&#39;</span><span class="p">,</span> <span class="nx">ptr</span><span class="p">,</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">|</span> <span class="nx">SQLITE_OPEN_CREATE</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span> <span class="o">!=</span> <span class="mf">0</span><span class="p">)</span>
535
+ <span class="linenos">15</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 database&#39;</span><span class="p">);</span>
536
+ <span class="linenos">16</span><span class="nx">db</span> <span class="o">=</span> <span class="nx">ptr</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span>
537
+ <span class="linenos">17</span>
538
+ <span class="linenos">18</span><span class="nx">sqlite3_close_v2</span><span class="p">(</span><span class="nx">db</span><span class="p">);</span>
539
+ </pre></div>
540
+ </div>
541
+ </section>
542
+ <section id="koffi-introspect">
543
+ <h4>koffi.introspect()<a class="headerlink" href="#koffi-introspect" title="Permalink to this heading">#</a></h4>
544
+ <p>In Koffi 1.x, <code class="docutils literal notranslate"><span class="pre">koffi.introspect()</span></code> would only work with struct types, and return the object passed to <code class="docutils literal notranslate"><span class="pre">koffi.struct()</span></code> to initialize the type. Now this function works with all types.</p>
545
+ <p>You can still get the list of struct members:</p>
546
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">StructType</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">struct</span><span class="p">(</span><span class="s1">&#39;StructType&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">dummy</span><span class="o">:</span> <span class="s1">&#39;int&#39;</span> <span class="p">});</span>
547
+ <span class="linenos">2</span>
548
+ <span class="linenos">3</span><span class="c1">// Koffi 1.x</span>
549
+ <span class="linenos">4</span><span class="kd">let</span> <span class="nx">members</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">introspect</span><span class="p">(</span><span class="nx">StructType</span><span class="p">);</span>
550
+ <span class="linenos">5</span>
551
+ <span class="linenos">6</span><span class="c1">// Koffi 2.x</span>
552
+ <span class="linenos">7</span><span class="kd">let</span> <span class="nx">members</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">introspect</span><span class="p">(</span><span class="nx">StructType</span><span class="p">).</span><span class="nx">members</span><span class="p">;</span>
553
+ </pre></div>
554
+ </div>
555
+ </section>
556
+ </section>
557
+ </section>
358
558
  </section>
359
559
 
360
560
  </article>
@@ -407,6 +607,11 @@
407
607
  <div class="toc-tree">
408
608
  <ul>
409
609
  <li><a class="reference internal" href="#">Changelog</a><ul>
610
+ <li><a class="reference internal" href="#history">History</a><ul>
611
+ <li><a class="reference internal" href="#koffi-2-0-0">Koffi 2.0.0</a></li>
612
+ <li><a class="reference internal" href="#koffi-1-3-12">Koffi 1.3.12</a></li>
613
+ <li><a class="reference internal" href="#koffi-1-3-11">Koffi 1.3.11</a></li>
614
+ <li><a class="reference internal" href="#koffi-1-3-10">Koffi 1.3.10</a></li>
410
615
  <li><a class="reference internal" href="#koffi-1-3-9">Koffi 1.3.9</a></li>
411
616
  <li><a class="reference internal" href="#koffi-1-3-8">Koffi 1.3.8</a></li>
412
617
  <li><a class="reference internal" href="#koffi-1-3-7">Koffi 1.3.7</a></li>
@@ -422,6 +627,17 @@
422
627
  <li><a class="reference internal" href="#koffi-1-2-1">Koffi 1.2.1</a></li>
423
628
  </ul>
424
629
  </li>
630
+ <li><a class="reference internal" href="#migration-guide">Migration guide</a><ul>
631
+ <li><a class="reference internal" href="#koffi-1-x-to-2-x">Koffi 1.x to 2.x</a><ul>
632
+ <li><a class="reference internal" href="#callback-types">Callback types</a></li>
633
+ <li><a class="reference internal" href="#opaque-handles">Opaque handles</a></li>
634
+ <li><a class="reference internal" href="#koffi-introspect">koffi.introspect()</a></li>
635
+ </ul>
636
+ </li>
637
+ </ul>
638
+ </li>
639
+ </ul>
640
+ </li>
425
641
  </ul>
426
642
 
427
643
  </div>
@@ -165,13 +165,17 @@
165
165
  <li class="toctree-l1"><a class="reference internal" href="platforms">Requirements</a></li>
166
166
  <li class="toctree-l1"><a class="reference internal" href="start">Quick start</a></li>
167
167
  <li class="toctree-l1"><a class="reference internal" href="types">Data types</a></li>
168
- <li class="toctree-l1"><a class="reference internal" href="functions">Function calls</a></li>
168
+ <li class="toctree-l1"><a class="reference internal" href="functions">Functions</a></li>
169
169
  <li class="toctree-l1"><a class="reference internal" href="memory">Memory usage</a></li>
170
170
  <li class="toctree-l1"><a class="reference internal" href="benchmarks">Benchmarks</a></li>
171
171
  <li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Contributing</a></li>
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