koffi 2.9.1 → 2.10.0

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 (93) hide show
  1. package/CHANGELOG.md +61 -48
  2. package/build/koffi/darwin_arm64/koffi.node +0 -0
  3. package/build/koffi/darwin_x64/koffi.node +0 -0
  4. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  5. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  6. package/build/koffi/freebsd_x64/koffi.node +0 -0
  7. package/build/koffi/linux_arm32/koffi.node +0 -0
  8. package/build/koffi/linux_arm64/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_riscv64/koffi.node +0 -0
  11. package/build/koffi/linux_x64/koffi.node +0 -0
  12. package/build/koffi/musl_x64/koffi.node +0 -0
  13. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  14. package/build/koffi/openbsd_x64/koffi.node +0 -0
  15. package/build/koffi/win32_arm64/koffi.node +0 -0
  16. package/build/koffi/win32_ia32/koffi.node +0 -0
  17. package/build/koffi/win32_x64/koffi.node +0 -0
  18. package/doc/README.md +27 -0
  19. package/doc/assets.ini +19 -0
  20. package/doc/develop.sh +14 -0
  21. package/doc/flaat/flaat.css +25 -0
  22. package/doc/flaat/flaat.js +150 -0
  23. package/doc/flaat/normal.css +335 -0
  24. package/doc/flaat/print.css +30 -0
  25. package/doc/flaat/small.css +101 -0
  26. package/doc/{benchmarks.md → pages/benchmarks.md} +14 -18
  27. package/doc/{callbacks.md → pages/callbacks.md} +27 -36
  28. package/doc/{contribute.md → pages/contribute.md} +10 -12
  29. package/doc/{functions.md → pages/functions.md} +29 -34
  30. package/doc/pages/index.md +20 -0
  31. package/doc/{input.md → pages/input.md} +28 -33
  32. package/doc/{migration.md → pages/migration.md} +7 -10
  33. package/doc/{misc.md → pages/misc.md} +54 -23
  34. package/doc/{output.md → pages/output.md} +17 -20
  35. package/doc/{packaging.md → pages/packaging.md} +19 -12
  36. package/doc/{platforms.md → pages/platforms.md} +25 -11
  37. package/doc/{pointers.md → pages/pointers.md} +13 -16
  38. package/doc/{start.md → pages/start.md} +12 -14
  39. package/doc/{unions.md → pages/unions.md} +5 -7
  40. package/doc/{variables.md → pages/variables.md} +7 -11
  41. package/doc/pages.ini +89 -0
  42. package/doc/static/koffi.css +21 -0
  43. package/doc/static/koffi.js +21 -0
  44. package/doc/static/koffi.png +0 -0
  45. package/doc/static/logo.webp +0 -0
  46. package/doc/static/print.css +22 -0
  47. package/doc/templates/page.html +48 -0
  48. package/index.js +2 -2
  49. package/indirect.js +2 -2
  50. package/package.json +2 -2
  51. package/src/koffi/CMakeLists.txt +6 -0
  52. package/src/koffi/examples/yao-pkg/README.md +17 -0
  53. package/src/koffi/examples/yao-pkg/index.js +2 -0
  54. package/src/koffi/examples/yao-pkg/package.json +22 -0
  55. package/src/koffi/src/call.cc +2 -0
  56. package/src/koffi/src/ffi.cc +40 -4
  57. package/src/koffi/src/util.cc +1 -1
  58. package/doc/Makefile +0 -20
  59. package/doc/benchmarks.xlsx +0 -0
  60. package/doc/changelog.md +0 -5
  61. package/doc/conf.py +0 -118
  62. package/doc/index.rst +0 -47
  63. package/doc/make.bat +0 -35
  64. package/doc/poetry.lock +0 -521
  65. package/doc/pyproject.toml +0 -19
  66. package/doc/static/bench_linux.png +0 -0
  67. package/doc/static/bench_windows.png +0 -0
  68. package/doc/static/custom.css +0 -70
  69. package/doc/static/node_c.webp +0 -0
  70. package/doc/static/opensans/LICENSE.txt +0 -202
  71. package/doc/static/opensans/OpenSans.css +0 -39
  72. package/doc/static/opensans/OpenSans_v17_Latin_Bold.woff +0 -0
  73. package/doc/static/opensans/OpenSans_v17_Latin_Bold.woff2 +0 -0
  74. package/doc/static/opensans/OpenSans_v17_Latin_BoldItalic.woff +0 -0
  75. package/doc/static/opensans/OpenSans_v17_Latin_BoldItalic.woff2 +0 -0
  76. package/doc/static/opensans/OpenSans_v17_Latin_Italic.woff +0 -0
  77. package/doc/static/opensans/OpenSans_v17_Latin_Italic.woff2 +0 -0
  78. package/doc/static/opensans/OpenSans_v17_Latin_Regular.woff +0 -0
  79. package/doc/static/opensans/OpenSans_v17_Latin_Regular.woff2 +0 -0
  80. package/doc/static/perf_linux_20220623.png +0 -0
  81. package/doc/static/perf_linux_20220623_2.png +0 -0
  82. package/doc/static/perf_linux_20220627.png +0 -0
  83. package/doc/static/perf_linux_20220628.png +0 -0
  84. package/doc/static/perf_linux_20220812.png +0 -0
  85. package/doc/static/perf_windows_20220623.png +0 -0
  86. package/doc/static/perf_windows_20220623_2.png +0 -0
  87. package/doc/static/perf_windows_20220627.png +0 -0
  88. package/doc/static/perf_windows_20220628.png +0 -0
  89. package/doc/static/perf_windows_20220812.png +0 -0
  90. package/doc/templates/badges.html +0 -7
  91. package/doc/templates/logo.html +0 -3
  92. /package/doc/static/{perf_linux_20231028.png → perf_linux.png} +0 -0
  93. /package/doc/static/{perf_windows_20231028.png → perf_windows.png} +0 -0
@@ -0,0 +1,335 @@
1
+ /* Copyright (C) 2024 Niels Martignène <niels.martignene@protonmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the “Software”), to deal in
5
+ the Software without restriction, including without limitation the rights to use,
6
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
7
+ Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
+ OTHER DEALINGS IN THE SOFTWARE. */
21
+
22
+ html {
23
+ --top_height: 90px;
24
+ --top_padding: 6px;
25
+ --small_height: 80px;
26
+
27
+ height: 100%;
28
+ scroll-padding-top: calc(var(--top_height) + 10px);
29
+ }
30
+
31
+ body {
32
+ min-height: 100%;
33
+ margin: 0;
34
+ padding: 0;
35
+
36
+ font-family: 'Open Sans', sans-serif;
37
+ font-size: 17px;
38
+ line-height: 1.5;
39
+
40
+ background: white;
41
+ color: #383838;
42
+
43
+ display: flex;
44
+ flex-direction: column;
45
+ }
46
+
47
+ a {
48
+ color: var(--primary_color, #383838);
49
+ cursor: pointer;
50
+ text-decoration: none;
51
+ }
52
+ a:hover { text-decoration: underline; }
53
+ a:has(> img) { text-decoration: none !important; }
54
+
55
+ #top {
56
+ position: sticky;
57
+ top: 0;
58
+ background: white;
59
+ z-index: 9;
60
+ border-bottom: 2px solid white;
61
+ transition: border-bottom-color 0.4s ease;
62
+ }
63
+ #top.border { border-bottom-color: #383838; }
64
+ #top menu {
65
+ position: sticky;
66
+ top: 0;
67
+ box-sizing: border-box;
68
+ max-width: 1200px;
69
+ height: var(--top_height);
70
+ box-sizing: border-box;
71
+ margin: 0 auto;
72
+ padding: var(--top_padding);
73
+ overflow: visible;
74
+ z-index: 1;
75
+ display: flex;
76
+ align-items: center;
77
+ gap: 10px;
78
+ }
79
+ #top li {
80
+ position: relative;
81
+ list-style-type: none;
82
+ padding-left: 8px;
83
+ border-left: 2px solid rgba(0, 0, 0, 0);
84
+ }
85
+ #top li a {
86
+ color: #383838;
87
+ text-decoration: none;
88
+ }
89
+ #top li > div a.category {
90
+ cursor: default;
91
+ pointer-events: none;
92
+ }
93
+ #top li > a {
94
+ display: block;
95
+ border-bottom: 1px solid #383838;
96
+ text-transform: uppercase;
97
+ }
98
+ #top li > a:hover, #top li.active > a {
99
+ margin-bottom: -1px;
100
+ border-bottom: 2px solid var(--primary_color);
101
+ }
102
+ #top li > a.active { font-weight: bold; }
103
+ #top li > div { display: none; }
104
+ .nojs #top li:has(> div):hover, #top li:has(> div).active { border-left-color: var(--primary_color); }
105
+ .nojs #top li:has(> div):hover > a, #top li:has(> div).active > a {
106
+ margin-bottom: 1px;
107
+ border-bottom: none;
108
+ }
109
+ .nojs #top li:hover > div, #top li.active > div {
110
+ position: absolute;
111
+ margin-top: 0px;
112
+ margin-left: -10px;
113
+ width: 220px;
114
+ padding: 12px 1em 10px 1em;
115
+ display: flex;
116
+ flex-direction: column;
117
+ background: white;
118
+ border-left: 2px solid var(--primary_color);
119
+ border-bottom: 2px solid var(--primary_color);
120
+ }
121
+ #top li > div > a { margin-top: 3px; }
122
+ #top li > div > a.active { font-weight: bold; }
123
+ #top li > div > a:hover { text-decoration: underline; }
124
+
125
+ #logo {
126
+ height: 70%;
127
+ object-fit: contain;
128
+ margin-right: 2em;
129
+ transition: filter 0.4s ease;
130
+ }
131
+ #logo > img {
132
+ width: 100%;
133
+ height: 100%;
134
+ object-fit: contain;
135
+ }
136
+
137
+ #side menu {
138
+ margin: 0;
139
+ padding: 8px;
140
+ width: 224px;
141
+ box-sizing: border-box;
142
+
143
+ position: fixed;
144
+ left: calc(50% + 360px);
145
+ top: calc(var(--top_height) + 34px);
146
+
147
+ background: #fdfdfd;
148
+ border: 2px solid #383838;
149
+ }
150
+ #side li { list-style-type: none; }
151
+ #side a {
152
+ display: block;
153
+ padding: 1px;
154
+ color: #383838;
155
+ text-decoration: none;
156
+ }
157
+ #side a:hover { text-decoration: underline; }
158
+ #side a.active { font-weight: bold; }
159
+ #side a.lv1 { padding-left: 12px; }
160
+ #side a.lv2 { padding-left: 27px; }
161
+ #side a.lv3 { padding-left: 42px; }
162
+ #side a.lv4 { padding-left: 57px; }
163
+ #side a.lv5 { padding-left: 72px; }
164
+ #side a.lv6 { padding-left: 87px; }
165
+
166
+ #deploy { display: none; }
167
+
168
+ main {
169
+ flex: 1;
170
+ width: 100%;
171
+ max-width: 1200px;
172
+ box-sizing: border-box;
173
+ margin: 20px auto 0 auto;
174
+ padding: 0 16px 16px 16px;
175
+ }
176
+ #side ~ main { padding-right: 290px; }
177
+
178
+ footer {
179
+ padding: 0.5em;
180
+ background: #f6f6f9;
181
+ display: flex;
182
+ gap: 1.5em;
183
+ align-items: center;
184
+ justify-content: center;
185
+ }
186
+ footer > img { filter: saturate(0%) brightness(0); }
187
+
188
+ p { margin: 1em 0 0 0; }
189
+ p:first-child, h1 + p, h2 + p, h3 + p { margin-top: 0; }
190
+
191
+ main img { max-width: 100%; }
192
+
193
+ h1 {
194
+ margin: 0 0 0.5em 0;
195
+ font-size: 1.6em;
196
+ text-transform: uppercase;
197
+ font-weight: normal;
198
+ color: #383838;
199
+ font-weight: bold;
200
+ }
201
+ h2 {
202
+ margin: 0 0 1em 0;
203
+ display: table;
204
+ padding: 2px 14px 2px 30px;
205
+ background: #191f22;
206
+ font-size: 1.2em;
207
+ font-weight: normal;
208
+ text-transform: uppercase;
209
+ color: white;
210
+ }
211
+ h3 {
212
+ margin: 0 0 0.8em 0;
213
+ display: table;
214
+ padding: 2px 14px 2px 40px;
215
+ background: #ddd;
216
+ font-size: 1.1em;
217
+ font-weight: normal;
218
+ font-style: italic;
219
+ text-transform: uppercase;
220
+ color: #383838;
221
+ }
222
+ * + h1, * + h2, * + h3 { margin-top: 1.2em; }
223
+
224
+ table {
225
+ margin: 1em auto;
226
+ border-collapse: collapse;
227
+ }
228
+ th {
229
+ padding: 0.5em;
230
+ background: #fafafa;
231
+ border: 1px solid #ebebeb;
232
+ }
233
+ thead th { text-align: center; }
234
+ tbody th {
235
+ text-align: left;
236
+ font-weight: normal;
237
+ font-style: italic;
238
+ }
239
+ td {
240
+ padding: 0.5em;
241
+ background: white;
242
+ border: 1px solid #ebebeb;
243
+ }
244
+ th.center, td.center { text-align: center; }
245
+ th.right, td.right { text-align: right; }
246
+
247
+ table + div.legend {
248
+ margin-top: calc(-1em + 2px);
249
+ text-align: center;
250
+ font-size: 0.8em;
251
+ }
252
+
253
+ .buttons {
254
+ margin: 1em;
255
+ display: flex;
256
+ gap: 20px;
257
+ justify-content: center;
258
+ flex-wrap: wrap;
259
+ }
260
+ .buttons > a {
261
+ display: block;
262
+ width: 40%;
263
+ min-width: 250px;
264
+ background: var(--secondary_color);
265
+ color: white;
266
+ padding: 0.6em 1em;
267
+ text-decoration: none;
268
+ text-align: center;
269
+ }
270
+ .buttons > a:hover {
271
+ filter: brightness(80%) contrast(150%);
272
+ color: white;
273
+ }
274
+
275
+ code:not(.hljs) {
276
+ padding: 2px 6px;
277
+ font-family: monospace;
278
+ font-size: 14px;
279
+ background: #eee;
280
+ }
281
+ pre > code:not(.hljs) {
282
+ padding: 0;
283
+ font-size: inherit;
284
+ background: transparent;
285
+ }
286
+
287
+ pre {
288
+ position: relative;
289
+ margin: 1em 20px;
290
+ padding: 0;
291
+ border: 1px solid #ebebeb;
292
+ background: #ffffff;
293
+ overflow: auto;
294
+ font-size: 12px;
295
+ z-index: 0;
296
+ }
297
+ .nojs pre { padding: 6px; }
298
+
299
+ .alert {
300
+ margin: 1.8em 1em 1.4em 1em;
301
+ padding: 0.8em 1em;
302
+ background: #fcfcfc;
303
+ border-left: 3px solid var(--color);
304
+ }
305
+ .alert:first-child { margin-top: 0; }
306
+ .alert > .title {
307
+ font-weight: bold;
308
+ color: var(--color);
309
+ }
310
+ .alert > .title::after { content: var(--text); }
311
+ .alert.note {
312
+ --color: #316dca;
313
+ --text: 'Note';
314
+ }
315
+ .alert.tip {
316
+ --color: #347d39;
317
+ --text: 'Tip';
318
+ }
319
+ .alert.important {
320
+ --color: #8256d0;
321
+ --text: '⚠\FE0E Important';
322
+ }
323
+ .alert.warning {
324
+ --color: #966600;
325
+ --text: '⚠\FE0E Warning';
326
+ }
327
+ .alert.caution {
328
+ --color: #c93c37;
329
+ --text: '⚠\FE0E Caution';
330
+ }
331
+
332
+ .footnotes {
333
+ margin: 2em 1em;
334
+ font-style: italic;
335
+ }
@@ -0,0 +1,30 @@
1
+ /* Copyright (C) 2024 Niels Martignène <niels.martignene@protonmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the “Software”), to deal in
5
+ the Software without restriction, including without limitation the rights to use,
6
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
7
+ Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
+ OTHER DEALINGS IN THE SOFTWARE. */
21
+
22
+ @media print {
23
+ #top { display: none; }
24
+ #side { display: none; }
25
+
26
+ main { padding-right: 16px !important; }
27
+ footer { display: none; }
28
+
29
+ h1:not(:first-child) { break-before: page; }
30
+ }
@@ -0,0 +1,101 @@
1
+ /* Copyright (C) 2024 Niels Martignène <niels.martignene@protonmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the “Software”), to deal in
5
+ the Software without restriction, including without limitation the rights to use,
6
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
7
+ Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
+ OTHER DEALINGS IN THE SOFTWARE. */
21
+
22
+ @media screen and (max-width: 1300px) {
23
+ #side menu {
24
+ width: auto;
25
+ margin: 16px;
26
+ padding: 16px;
27
+ position: static;
28
+ }
29
+
30
+ main { padding-right: 16px !important; }
31
+ }
32
+
33
+ @media screen and (max-width: 960px) {
34
+ html { scroll-padding-top: calc(var(--small_height) + 10px); }
35
+
36
+ #top menu {
37
+ height: var(--small_height);
38
+ padding-left: 60px;
39
+ flex-direction: column;
40
+ gap: 0;
41
+ align-items: start;
42
+ z-index: 8;
43
+ }
44
+ #top li a {
45
+ font-size: 1.1em;
46
+ line-height: 1.6em;
47
+ }
48
+ #top li > a:hover, #top li.active > a { margin-bottom: -2px; }
49
+ #top li > a { border-bottom: none; }
50
+ .js #top li > a, .nojs #top:not(:hover) li > a { display: none; }
51
+ .nojs #top:hover menu, #top.active menu {
52
+ height: auto;
53
+ gap: 4px;
54
+ }
55
+ #top.active li > a, .nojs #top li.active > a { display: block !important; }
56
+ #top li.active > div, .nojs #top li:hover > div { position: static; }
57
+
58
+ #side a {
59
+ font-size: 1.1em;
60
+ line-height: 1.6em;
61
+ }
62
+
63
+ footer {
64
+ flex-direction: column;
65
+ padding: 0.5em;
66
+ gap: 6px;
67
+ text-align: center;
68
+ }
69
+ footer > img { display: none; }
70
+
71
+ #logo {
72
+ height: 100%;
73
+ margin: 0 auto;
74
+ transform: translate(-10px, 0);
75
+ }
76
+ .js #top.active #logo { display: none; }
77
+ .nojs #top:hover #logo { display: none; }
78
+
79
+ #deploy {
80
+ display: block !important;
81
+ position: fixed;
82
+ width: 42px;
83
+ height: 40px;
84
+ top: 10px;
85
+ left: 8px;
86
+ padding: 0;
87
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAOUlEQVQ4T2O0sLD4z0ADwDhqMCxUGWkQvGAjRw2GhyztgmI0HcPTMc2CYjSDDOGygmapYtRgWKoAAGrCE+uzrIQ5AAAAAElFTkSuQmCC");
88
+ background-repeat: no-repeat;
89
+ background-position: center;
90
+ z-index: 999;
91
+ cursor: pointer;
92
+ }
93
+ .nojs #deploy { pointer-events: none; }
94
+
95
+ pre { margin: 1em 0; }
96
+
97
+ .alert {
98
+ margin-left: 0.4em;
99
+ margin-right: 0.4em;
100
+ }
101
+ }
@@ -1,6 +1,4 @@
1
- # Benchmarks
2
-
3
- ## Overview
1
+ # Overview
4
2
 
5
3
  Here is a quick overview of the execution time of Koffi calls on three benchmarks, where it is compared to a theoretical ideal FFI implementation (approximated with pre-compiled static N-API glue code):
6
4
 
@@ -8,20 +6,18 @@ Here is a quick overview of the execution time of Koffi calls on three benchmark
8
6
  - The second benchmark is based on `atoi()` calls
9
7
  - The third benchmark is based on [Raylib](https://www.raylib.com/)
10
8
 
11
- <table style="margin: 0 auto;">
12
- <tr>
13
- <td><a href="_static/perf_linux_20231028.png" target="_blank"><img src="_static/perf_linux_20231028.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
14
- <td><a href="_static/perf_windows_20231028.png" target="_blank"><img src="_static/perf_windows_20231028.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
15
- </tr>
16
- </table>
9
+ <p style="text-align: center;">
10
+ <a href="{{ ASSET static/perf_linux.png }}" target="_blank"><img src="{{ ASSET static/perf_linux.png }}" alt="Linux x86_64 performance" style="width: 350px;"/></a>
11
+ <a href="{{ ASSET static/perf_windows.png }}" target="_blank"><img src="{{ ASSET static/perf_windows.png }}" alt="Windows x86_64 performance" style="width: 350px;"/></a>
12
+ </p>
17
13
 
18
14
  These results are detailed and explained below, and compared to node-ffi/node-ffi-napi.
19
15
 
20
- ## Linux x86_64
16
+ # Linux x86_64
21
17
 
22
18
  The results presented below were measured on my x86_64 Linux machine (Intel® Core™ i5-4460).
23
19
 
24
- ### rand results
20
+ ## rand results
25
21
 
26
22
  This test is based around repeated calls to a simple standard C function `rand`, and has three implementations:
27
23
 
@@ -37,7 +33,7 @@ rand_node_ffi | 32750 ns | x0.02 | +4576%
37
33
 
38
34
  Because rand is a pretty small function, the FFI overhead is clearly visible.
39
35
 
40
- ### atoi results
36
+ ## atoi results
41
37
 
42
38
  This test is similar to the rand one, but it is based on `atoi`, which takes a string parameter. Javascript (V8) to C string conversion is relatively slow and heavy.
43
39
 
@@ -49,7 +45,7 @@ atoi_node_ffi | 121670 ns | x0.008 | +11738%
49
45
 
50
46
  Because atoi is a pretty small function, the FFI overhead is clearly visible.
51
47
 
52
- ### Raylib results
48
+ ## Raylib results
53
49
 
54
50
  This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in previous benchmarks, thus the FFI overhead is reduced. In this implementation, Koffi is compared to:
55
51
 
@@ -63,11 +59,11 @@ raylib_node_raylib | 26.3 µs | x1.00 | (ref)
63
59
  raylib_koffi | 28.0 µs | x0.94 | +6%
64
60
  raylib_node_ffi | 87.0 µs | x0.30 | +230%
65
61
 
66
- ## Windows x86_64
62
+ # Windows x86_64
67
63
 
68
64
  The results presented below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460).
69
65
 
70
- ### rand results
66
+ ## rand results
71
67
 
72
68
  This test is based around repeated calls to a simple standard C function `rand`, and has three implementations:
73
69
 
@@ -83,7 +79,7 @@ rand_node_ffi | 35640 ns | x0.02 | +4048%
83
79
 
84
80
  Because rand is a pretty small function, the FFI overhead is clearly visible.
85
81
 
86
- ### atoi results
82
+ ## atoi results
87
83
 
88
84
  This test is similar to the rand one, but it is based on `atoi`, which takes a string parameter. Javascript (V8) to C string conversion is relatively slow and heavy.
89
85
 
@@ -97,7 +93,7 @@ atoi_node_ffi | 136890 ns | x0.010 | +10144%
97
93
 
98
94
  Because atoi is a pretty small function, the FFI overhead is clearly visible.
99
95
 
100
- ### Raylib results
96
+ ## Raylib results
101
97
 
102
98
  This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in the atoi benchmark, thus the FFI overhead is reduced. In this implementation, Koffi is compared to:
103
99
 
@@ -111,7 +107,7 @@ raylib_node_raylib | 27.3 µs | x1.00 | (ref)
111
107
  raylib_koffi | 29.8 µs | x0.92 | +9%
112
108
  raylib_node_ffi | 96.3 µs | x0.28 | +253%
113
109
 
114
- ## Running benchmarks
110
+ # Running benchmarks
115
111
 
116
112
  Please note that all benchmark results on this page are made with Clang-built binaries.
117
113
 
@@ -1,12 +1,4 @@
1
- # Javascript callbacks
2
-
3
- *Changed in Koffi 2.4*
4
-
5
- ```{note}
6
- The function `koffi.proto()` was introduced in Koffi 2.4, it was called `koffi.callback()` in earlier versions.
7
- ```
8
-
9
- ## Callback types
1
+ # Callback types
10
2
 
11
3
  *Changed in Koffi 2.7*
12
4
 
@@ -22,8 +14,10 @@ const ExampleCallback = koffi.proto('ExampleCallback', 'void', ['int']);
22
14
  // With the prototype parser, this callback expects a double and float, and returns the sum as a double
23
15
  const AddDoubleFloat = koffi.proto('double AddDoubleFloat(double d, float f)');
24
16
  ```
17
+ > [!NOTE]
18
+ > The function `koffi.proto()` was introduced in Koffi 2.4, it was called `koffi.callback()` in earlier versions.
25
19
 
26
- For alternative [calling conventions](functions.md#calling-conventions) (such as `stdcall` on Windows x86 32-bit), you can specify as the first argument with the classic syntax, or after the return type in prototype strings, like this:
20
+ For alternative [calling conventions](functions#calling-conventions) (such as `stdcall` on Windows x86 32-bit), you can specify as the first argument with the classic syntax, or after the return type in prototype strings, like this:
27
21
 
28
22
  ```js
29
23
  const HANDLE = koffi.pointer('HANDLE', koffi.opaque());
@@ -34,25 +28,23 @@ const EnumWindowsProc = koffi.proto('bool __stdcall EnumWindowsProc (HWND hwnd,
34
28
  const EnumWindowsProc = koffi.proto('__stdcall', 'EnumWindowsProc', 'bool', ['HWND', 'long']);
35
29
  ```
36
30
 
37
- ```{warning}
38
- You have to make sure you **get the calling convention right** (such as specifying __stdcall for a Windows API callback), or your code will crash on Windows 32-bit.
39
-
40
- Before Koffi 2.7, it was *impossible to use an alternative callback calling convention with the classic syntax*. Use a prototype string or *upgrade to Koffi 2.7* to solve this limitation.
41
- ```
31
+ > [!WARNING]
32
+ > You have to make sure you **get the calling convention right** (such as specifying __stdcall for a Windows API callback), or your code will crash on Windows 32-bit.
33
+ >
34
+ > Before Koffi 2.7, it was *impossible to use an alternative callback calling convention with the classic syntax*. Use a prototype string or *upgrade to Koffi 2.7* to solve this limitation.
42
35
 
43
36
  Once your callback type is declared, you can use a pointer to it in struct definitions, as function parameters and/or return types, or to call/decode function pointers.
44
37
 
45
- ```{note}
46
- Callbacks **have changed in version 2.0**.
38
+ > [!NOTE]
39
+ > Callbacks **have changed in version 2.0**.
40
+ >
41
+ > In Koffi 1.x, callbacks were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer.
42
+ >
43
+ > 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.
44
+ >
45
+ > Consult the [migration guide](migration) for more information.
47
46
 
48
- In Koffi 1.x, callbacks were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer.
49
-
50
- 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.
51
-
52
- Consult the [migration guide](migration.md) for more information.
53
- ```
54
-
55
- ## Transient and registered callbacks
47
+ # Transient and registered callbacks
56
48
 
57
49
  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.
58
50
 
@@ -61,9 +53,9 @@ Thus, Koffi distinguishes two callback modes:
61
53
  - [Transient callbacks](#transient-callbacks) can only be called while the C function they are passed to is running, and are invalidated when it returns. If the C function calls the callback later, the behavior is undefined, though Koffi tries to detect such cases. If it does, an exception will be thrown, but this is no guaranteed. However, they are simple to use, and don't require any special handling.
62
54
  - [Registered callbacks](#registered-callbacks) can be called at any time, but they must be manually registered and unregistered. A limited number of registered callbacks can exist at the same time.
63
55
 
64
- You need to specify the correct [calling convention](functions.md#calling-conventions) on x86 platforms, or the behavior is undefined (Node will probably crash). Only *cdecl* and *stdcall* callbacks are supported.
56
+ You need to specify the correct [calling convention](functions#calling-conventions) on x86 platforms, or the behavior is undefined (Node will probably crash). Only *cdecl* and *stdcall* callbacks are supported.
65
57
 
66
- ### Transient callbacks
58
+ ## Transient callbacks
67
59
 
68
60
  Use transient callbacks when the native C function only needs to call them while it runs (e.g. qsort, progress callback, `sqlite3_exec`). Here is a small example with the C part and the JS part.
69
61
 
@@ -101,7 +93,7 @@ console.log(ret);
101
93
  // 42
102
94
  ```
103
95
 
104
- ### Registered callbacks
96
+ ## Registered callbacks
105
97
 
106
98
  *New in Koffi 2.0 (explicit this binding in Koffi 2.2)*
107
99
 
@@ -164,15 +156,15 @@ let cb1 = koffi.register(store.get, 'IntCallback *'); // If a C function calls c
164
156
  let cb2 = koffi.register(store, store.get, 'IntCallback *'); // However in this case, this will match the store object
165
157
  ```
166
158
 
167
- ## Special considerations
159
+ # Special considerations
168
160
 
169
- ### Decoding pointer arguments
161
+ ## Decoding pointer arguments
170
162
 
171
163
  *New in Koffi 2.2, changed in Koffi 2.3*
172
164
 
173
165
  Koffi does not have enough information to convert callback pointer arguments to an appropriate JS value. In this case, your JS function will receive an opaque *External* object.
174
166
 
175
- You can pass this value through to another C function that expects a pointer of the same type, or you can use [koffi.decode()](variables.md#decode-to-js-values) function to decode pointer arguments.
167
+ You can pass this value through to another C function that expects a pointer of the same type, or you can use [koffi.decode()](variables#decode-to-js-values) function to decode pointer arguments.
176
168
 
177
169
  The following examples uses it to sort an array of strings in-place with the standard C function `qsort()`:
178
170
 
@@ -197,7 +189,7 @@ qsort(koffi.as(array, 'char **'), array.length, koffi.sizeof('void *'), (ptr1, p
197
189
  console.log(array); // Prints ['123', 'bar', 'foo', 'foobar']
198
190
  ```
199
191
 
200
- ### Asynchronous callbacks
192
+ ## Asynchronous callbacks
201
193
 
202
194
  *New in Koffi 2.2.2*
203
195
 
@@ -208,11 +200,10 @@ JS execution is inherently single-threaded, so JS callbacks must run on the main
208
200
 
209
201
  In both cases, Koffi will queue the call back to JS to run on the main thread, as soon as the JS event loop has a chance to run (for example when you await a promise).
210
202
 
211
- ```{warning}
212
- Be careful, you can easily get into a deadlock situation if you call a callback from a secondary thread and your main thread never lets the JS event loop run (for example, if the main thread waits for the secondary thread to finish something itself).
213
- ```
203
+ > [!WARNING]
204
+ > Be careful, you can easily get into a deadlock situation if you call a callback from a secondary thread and your main thread never lets the JS event loop run (for example, if the main thread waits for the secondary thread to finish something itself).
214
205
 
215
- ## Handling of exceptions
206
+ # Handling of exceptions
216
207
 
217
208
  If an exception happens inside the JS callback, the C API will receive 0 or NULL (depending on the return value type).
218
209