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
package/CMakeLists.txt CHANGED
@@ -113,8 +113,13 @@ endif()
113
113
  if(NOT MSVC OR CMAKE_C_COMPILER_ID MATCHES "[Cc]lang")
114
114
  # Restore C/C++ compiler sanity
115
115
 
116
- target_compile_options(koffi PRIVATE -fno-exceptions -fno-strict-aliasing -fwrapv
117
- -fno-delete-null-pointer-checks)
116
+ if(NOT MSVC)
117
+ target_compile_options(koffi PRIVATE -fno-exceptions -fno-strict-aliasing -fwrapv
118
+ -fno-delete-null-pointer-checks)
119
+ else()
120
+ target_compile_options(koffi PRIVATE -fno-strict-aliasing /clang:-fwrapv
121
+ -fno-delete-null-pointer-checks)
122
+ endif()
118
123
 
119
124
  check_cxx_compiler_flag(-fno-finite-loops use_no_finite_loops)
120
125
  if(use_no_finite_loops)
package/ChangeLog.md CHANGED
@@ -1,12 +1,50 @@
1
1
  # Changelog
2
2
 
3
- ## Koffi 1.3.11
3
+ ## History
4
+
5
+ ### Koffi 2.0.1
6
+
7
+ **Main changes:**
8
+
9
+ - Return `undefined` (instead of null) for `void` functions
10
+
11
+ ### Koffi 2.0.0
12
+
13
+ **Major new features:**
14
+
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
17
+ - Support named pointer types
18
+ - Support complex type specifications outside of prototype parser
19
+
20
+ **Minor new features:**
21
+
22
+ - Support type aliases with `koffi.alias()`
23
+ - Add `koffi.resolve()` to resolve type strings
24
+ - Expose all primitive type aliases in `koffi.types`
25
+ - Correctly pass exceptions thrown in JS callbacks
26
+
27
+ **Breaking API changes:**
28
+
29
+ - Change handling of callback types, which must be used through pointers
30
+ - Change handling of opaque handles, which must be used through pointers
31
+ - Support all types in `koffi.introspect(type)`
32
+
33
+ Consult the [migration guide](changes.md#migration-guide) for more information.
34
+
35
+ ### Koffi 1.3.12
36
+
37
+ **Main fixes:**
38
+
39
+ - Fix support for Yarn package manager
40
+
41
+ ### Koffi 1.3.11
4
42
 
5
43
  **Main fixes:**
6
44
 
7
45
  - Fix broken parsing of `void *` when used for first parameter
8
46
 
9
- ## Koffi 1.3.10
47
+ ### Koffi 1.3.10
10
48
 
11
49
  **Main fixes:**
12
50
 
@@ -18,13 +56,13 @@
18
56
 
19
57
  - Various documentation fixes and improvements
20
58
 
21
- ## Koffi 1.3.9
59
+ ### Koffi 1.3.9
22
60
 
23
61
  **Main fixes:**
24
62
 
25
63
  - Fix prebuild compatibility with Electron on Windows x64
26
64
 
27
- ## Koffi 1.3.8
65
+ ### Koffi 1.3.8
28
66
 
29
67
  **Main changes:**
30
68
 
@@ -35,7 +73,7 @@
35
73
 
36
74
  - Fix and harmonize a few error messages
37
75
 
38
- ## Koffi 1.3.7
76
+ ### Koffi 1.3.7
39
77
 
40
78
  **Main fixes:**
41
79
 
@@ -48,7 +86,7 @@
48
86
  - Add str/str16 type aliases for string/string16
49
87
  - Various documentation fixes and improvements
50
88
 
51
- ## Koffi 1.3.6
89
+ ### Koffi 1.3.6
52
90
 
53
91
  **Main fixes:**
54
92
 
@@ -60,7 +98,7 @@
60
98
  - Prebuild with Clang for Windows x64 and Linux x64 binaries
61
99
  - Various documentation improvements
62
100
 
63
- ## Koffi 1.3.5
101
+ ### Koffi 1.3.5
64
102
 
65
103
  **Main changes:**
66
104
 
@@ -72,13 +110,13 @@
72
110
  - Reduce default async memory stack and heap size
73
111
  - Various documentation improvements
74
112
 
75
- ## Koffi 1.3.4
113
+ ### Koffi 1.3.4
76
114
 
77
115
  **Main fixes:**
78
116
 
79
117
  - Fix possible OpenBSD i386 crash with `(void)` functions
80
118
 
81
- ## Koffi 1.3.3
119
+ ### Koffi 1.3.3
82
120
 
83
121
  **Main fixes:**
84
122
 
@@ -90,20 +128,20 @@
90
128
  - Disable unsafe compiler optimizations
91
129
  - Various documentation improvements
92
130
 
93
- ## Koffi 1.3.2
131
+ ### Koffi 1.3.2
94
132
 
95
133
  **Main fixes:**
96
134
 
97
135
  - Support compilation in C++14 mode (graceful degradation)
98
136
  - Support older toolchains on Linux (tested on Debian 9)
99
137
 
100
- ## Koffi 1.3.1
138
+ ### Koffi 1.3.1
101
139
 
102
140
  **Main fixes:**
103
141
 
104
142
  - The prebuilt binary is tested when Koffi is installed, and a rebuild happens if it fails to load
105
143
 
106
- ## Koffi 1.3.0
144
+ ### Koffi 1.3.0
107
145
 
108
146
  **Major changes:**
109
147
 
@@ -119,19 +157,19 @@
119
157
  - Detect floating-point ABI before using prebuilt binaries (ARM32, RISC-V)
120
158
  - Forbid duplicate member names in struct types
121
159
 
122
- ## Koffi 1.2.4
160
+ ### Koffi 1.2.4
123
161
 
124
162
  **New features:**
125
163
 
126
164
  - Windows ARM64 is now supported
127
165
 
128
- ## Koffi 1.2.3
166
+ ### Koffi 1.2.3
129
167
 
130
168
  **New features:**
131
169
 
132
170
  - A prebuilt binary for macOS ARM64 (M1) is now included
133
171
 
134
- ## Koffi 1.2.1
172
+ ### Koffi 1.2.1
135
173
 
136
174
  This entry documents changes since version 1.1.0.
137
175
 
package/README.md CHANGED
@@ -23,6 +23,12 @@ RISC-V 64 [^3] | ⬜️ *N/A* | ✅ Yes | ⬜️ *N/A* | 🟨 Probab
23
23
 
24
24
  Go to the web site for more information: https://koffi.dev/
25
25
 
26
+ # Project history
27
+
28
+ You can consult the [changelog](https://koffi.dev/changes) on the official website.
29
+
30
+ Major version increments can include breaking API changes, use the [migration guide](https://koffi.dev/changes#migration-guide) for more information.
31
+
26
32
  # License
27
33
 
28
34
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
package/doc/changes.md CHANGED
@@ -1,2 +1,157 @@
1
1
  ```{include} ../ChangeLog.md
2
- ```
2
+ ```
3
+
4
+ ## Migration guide
5
+
6
+ ### Koffi 1.x to 2.x
7
+
8
+ 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.
9
+
10
+ You may need to change your code if you use:
11
+
12
+ - Callback functions
13
+ - Opaque handles
14
+ - `koffi.introspect()`
15
+
16
+ #### Callback types
17
+
18
+ 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: `void CallIt(CallbackType func)` in Koffi 1.x becomes `void CallIt(CallbackType *func)` in version 2.0 and newer.
19
+
20
+ Given the following C code:
21
+
22
+ ```c
23
+ #include <string.h>
24
+
25
+ int TransferToJS(const char *name, int age, int (*cb)(const char *str, int age))
26
+ {
27
+ char buf[64];
28
+ snprintf(buf, sizeof(buf), "Hello %s!", str);
29
+ return cb(buf, age);
30
+ }
31
+ ```
32
+
33
+ The two versions below illustrate the API difference between Koffi 1.x and Koffi 2.x:
34
+
35
+ ```js
36
+ // Koffi 1.x
37
+
38
+ const TransferCallback = koffi.callback('int TransferCallback(const char *str, int age)');
39
+
40
+ const TransferToJS = lib.func('TransferToJS', 'int', ['str', 'int', TransferCallback]);
41
+ // Equivalent to: const TransferToJS = lib.func('int TransferToJS(str s, int x, TransferCallback cb)');
42
+
43
+ let ret = TransferToJS('Niels', 27, (str, age) => {
44
+ console.log(str);
45
+ console.log('Your age is:', age);
46
+ return 42;
47
+ });
48
+ console.log(ret);
49
+ ```
50
+
51
+ ```js
52
+ // Koffi 2.x
53
+
54
+ const TransferCallback = koffi.callback('int TransferCallback(const char *str, int age)');
55
+
56
+ const TransferToJS = lib.func('TransferToJS', 'int', ['str', 'int', koffi.pointer(TransferCallback)]);
57
+ // Equivalent to: const TransferToJS = lib.func('int TransferToJS(str s, int x, TransferCallback *cb)');
58
+
59
+ let ret = TransferToJS('Niels', 27, (str, age) => {
60
+ console.log(str);
61
+ console.log('Your age is:', age);
62
+ return 42;
63
+ });
64
+ console.log(ret);
65
+ ```
66
+
67
+ Koffi 1.x only supported [transient callbacks](functions.md#javascript-callbacks), you must use Koffi 2.x for registered callbacks.
68
+
69
+ #### Opaque handles
70
+
71
+ 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.
72
+
73
+ For functions that return handles or pass them by parameter:
74
+
75
+ ```js
76
+ // Koffi 1.x
77
+
78
+ const FILE = koffi.handle('FILE');
79
+ const fopen = lib.func('fopen', 'FILE', ['str', 'str']);
80
+ const fopen = lib.func('fclose', 'int', ['FILE']);
81
+
82
+ let fp = fopen('EMPTY', 'wb');
83
+ if (!fp)
84
+ throw new Error('Failed to open file');
85
+ fclose(fp);
86
+ ```
87
+
88
+ ```js
89
+ // Koffi 2.x
90
+
91
+ const FILE = koffi.handle('FILE');
92
+ const fopen = lib.func('fopen', 'FILE *', ['str', 'str']);
93
+ const fopen = lib.func('fclose', 'int', ['FILE *']);
94
+
95
+ let fp = fopen('EMPTY', 'wb');
96
+ if (!fp)
97
+ throw new Error('Failed to open file');
98
+ fclose(fp);
99
+ ```
100
+
101
+ For functions that set opaque handles through output parameters (such as `sqlite3_open_v2`), you must now use a single element array as shown below:
102
+
103
+ ```js
104
+ // Koffi 1.x
105
+
106
+ const sqlite3 = koffi.handle('sqlite3');
107
+
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
+
111
+ const SQLITE_OPEN_READWRITE = 0x2;
112
+ const SQLITE_OPEN_CREATE = 0x4;
113
+
114
+ let db = {};
115
+
116
+ if (sqlite3_open_v2(':memory:', db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
117
+ throw new Error('Failed to open database');
118
+
119
+ sqlite3_close_v2(db);
120
+ ```
121
+
122
+ ```js
123
+ // Koffi 2.x
124
+
125
+ const sqlite3 = koffi.handle('sqlite3');
126
+
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
+
130
+ const SQLITE_OPEN_READWRITE = 0x2;
131
+ const SQLITE_OPEN_CREATE = 0x4;
132
+
133
+ let db = null;
134
+
135
+ let ptr = [null];
136
+ if (sqlite3_open_v2(':memory:', ptr, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
137
+ throw new Error('Failed to open database');
138
+ db = ptr[0];
139
+
140
+ sqlite3_close_v2(db);
141
+ ```
142
+
143
+ #### koffi.introspect()
144
+
145
+ In Koffi 1.x, `koffi.introspect()` would only work with struct types, and return the object passed to `koffi.struct()` to initialize the type. Now this function works with all types.
146
+
147
+ You can still get the list of struct members:
148
+
149
+ ```js
150
+ const StructType = koffi.struct('StructType', { dummy: 'int' });
151
+
152
+ // Koffi 1.x
153
+ let members = koffi.introspect(StructType);
154
+
155
+ // Koffi 2.x
156
+ let members = koffi.introspect(StructType).members;
157
+ ```
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 = [
package/doc/contribute.md CHANGED
@@ -111,7 +111,6 @@ node qemu.js info debian_x64
111
111
 
112
112
  The following features and improvements are planned, not necessarily in that order:
113
113
 
114
- - Provide better ways to automatically deal with caller/heap-allocated memory (strings, etc.)
115
114
  - Optimize passing of structs and arrays (avoid setting named properties one by one? separate HFA-specific helper functions?)
116
115
  - Automate Windows/AArch64 (qemu) and macOS/AArch64 (how? ... thanks Apple) tests
117
116
  - Create a real-world example, using several libraries (Raylib, SQLite, libsodium) to illustrate various C API styles
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
 
@@ -1,2 +1,157 @@
1
1
  ```{include} ../ChangeLog.md
2
- ```
2
+ ```
3
+
4
+ ## Migration guide
5
+
6
+ ### Koffi 1.x to 2.x
7
+
8
+ 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.
9
+
10
+ You may need to change your code if you use:
11
+
12
+ - Callback functions
13
+ - Opaque handles
14
+ - `koffi.introspect()`
15
+
16
+ #### Callback types
17
+
18
+ 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: `void CallIt(CallbackType func)` in Koffi 1.x becomes `void CallIt(CallbackType *func)` in version 2.0 and newer.
19
+
20
+ Given the following C code:
21
+
22
+ ```c
23
+ #include <string.h>
24
+
25
+ int TransferToJS(const char *name, int age, int (*cb)(const char *str, int age))
26
+ {
27
+ char buf[64];
28
+ snprintf(buf, sizeof(buf), "Hello %s!", str);
29
+ return cb(buf, age);
30
+ }
31
+ ```
32
+
33
+ The two versions below illustrate the API difference between Koffi 1.x and Koffi 2.x:
34
+
35
+ ```js
36
+ // Koffi 1.x
37
+
38
+ const TransferCallback = koffi.callback('int TransferCallback(const char *str, int age)');
39
+
40
+ const TransferToJS = lib.func('TransferToJS', 'int', ['str', 'int', TransferCallback]);
41
+ // Equivalent to: const TransferToJS = lib.func('int TransferToJS(str s, int x, TransferCallback cb)');
42
+
43
+ let ret = TransferToJS('Niels', 27, (str, age) => {
44
+ console.log(str);
45
+ console.log('Your age is:', age);
46
+ return 42;
47
+ });
48
+ console.log(ret);
49
+ ```
50
+
51
+ ```js
52
+ // Koffi 2.x
53
+
54
+ const TransferCallback = koffi.callback('int TransferCallback(const char *str, int age)');
55
+
56
+ const TransferToJS = lib.func('TransferToJS', 'int', ['str', 'int', koffi.pointer(TransferCallback)]);
57
+ // Equivalent to: const TransferToJS = lib.func('int TransferToJS(str s, int x, TransferCallback *cb)');
58
+
59
+ let ret = TransferToJS('Niels', 27, (str, age) => {
60
+ console.log(str);
61
+ console.log('Your age is:', age);
62
+ return 42;
63
+ });
64
+ console.log(ret);
65
+ ```
66
+
67
+ Koffi 1.x only supported [transient callbacks](functions.md#javascript-callbacks), you must use Koffi 2.x for registered callbacks.
68
+
69
+ #### Opaque handles
70
+
71
+ 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.
72
+
73
+ For functions that return handles or pass them by parameter:
74
+
75
+ ```js
76
+ // Koffi 1.x
77
+
78
+ const FILE = koffi.handle('FILE');
79
+ const fopen = lib.func('fopen', 'FILE', ['str', 'str']);
80
+ const fopen = lib.func('fclose', 'int', ['FILE']);
81
+
82
+ let fp = fopen('EMPTY', 'wb');
83
+ if (!fp)
84
+ throw new Error('Failed to open file');
85
+ fclose(fp);
86
+ ```
87
+
88
+ ```js
89
+ // Koffi 2.x
90
+
91
+ const FILE = koffi.handle('FILE');
92
+ const fopen = lib.func('fopen', 'FILE *', ['str', 'str']);
93
+ const fopen = lib.func('fclose', 'int', ['FILE *']);
94
+
95
+ let fp = fopen('EMPTY', 'wb');
96
+ if (!fp)
97
+ throw new Error('Failed to open file');
98
+ fclose(fp);
99
+ ```
100
+
101
+ For functions that set opaque handles through output parameters (such as `sqlite3_open_v2`), you must now use a single element array as shown below:
102
+
103
+ ```js
104
+ // Koffi 1.x
105
+
106
+ const sqlite3 = koffi.handle('sqlite3');
107
+
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
+
111
+ const SQLITE_OPEN_READWRITE = 0x2;
112
+ const SQLITE_OPEN_CREATE = 0x4;
113
+
114
+ let db = {};
115
+
116
+ if (sqlite3_open_v2(':memory:', db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
117
+ throw new Error('Failed to open database');
118
+
119
+ sqlite3_close_v2(db);
120
+ ```
121
+
122
+ ```js
123
+ // Koffi 2.x
124
+
125
+ const sqlite3 = koffi.handle('sqlite3');
126
+
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
+
130
+ const SQLITE_OPEN_READWRITE = 0x2;
131
+ const SQLITE_OPEN_CREATE = 0x4;
132
+
133
+ let db = null;
134
+
135
+ let ptr = [null];
136
+ if (sqlite3_open_v2(':memory:', ptr, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
137
+ throw new Error('Failed to open database');
138
+ db = ptr[0];
139
+
140
+ sqlite3_close_v2(db);
141
+ ```
142
+
143
+ #### koffi.introspect()
144
+
145
+ In Koffi 1.x, `koffi.introspect()` would only work with struct types, and return the object passed to `koffi.struct()` to initialize the type. Now this function works with all types.
146
+
147
+ You can still get the list of struct members:
148
+
149
+ ```js
150
+ const StructType = koffi.struct('StructType', { dummy: 'int' });
151
+
152
+ // Koffi 1.x
153
+ let members = koffi.introspect(StructType);
154
+
155
+ // Koffi 2.x
156
+ let members = koffi.introspect(StructType).members;
157
+ ```