koffi 2.0.0 → 2.1.0-beta.2

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 (127) hide show
  1. package/CMakeLists.txt +2 -9
  2. package/ChangeLog.md +25 -2
  3. package/benchmark/atoi_koffi.js +12 -8
  4. package/benchmark/atoi_napi.js +12 -8
  5. package/benchmark/atoi_node_ffi.js +11 -10
  6. package/benchmark/raylib_cc.cc +12 -9
  7. package/benchmark/raylib_koffi.js +15 -13
  8. package/benchmark/raylib_node_ffi.js +15 -13
  9. package/benchmark/raylib_node_raylib.js +14 -11
  10. package/build/qemu/2.1.0-beta.2/koffi_darwin_arm64.tar.gz +0 -0
  11. package/build/qemu/2.1.0-beta.2/koffi_darwin_x64.tar.gz +0 -0
  12. package/build/qemu/2.1.0-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
  13. package/build/qemu/2.1.0-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
  14. package/build/qemu/2.1.0-beta.2/koffi_freebsd_x64.tar.gz +0 -0
  15. package/build/qemu/2.1.0-beta.2/koffi_linux_arm32hf.tar.gz +0 -0
  16. package/build/qemu/2.1.0-beta.2/koffi_linux_arm64.tar.gz +0 -0
  17. package/build/qemu/2.1.0-beta.2/koffi_linux_ia32.tar.gz +0 -0
  18. package/build/qemu/2.1.0-beta.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  19. package/build/qemu/2.1.0-beta.2/koffi_linux_x64.tar.gz +0 -0
  20. package/build/qemu/2.1.0-beta.2/koffi_openbsd_ia32.tar.gz +0 -0
  21. package/build/qemu/2.1.0-beta.2/koffi_openbsd_x64.tar.gz +0 -0
  22. package/build/qemu/2.1.0-beta.2/koffi_win32_arm64.tar.gz +0 -0
  23. package/build/qemu/2.1.0-beta.2/koffi_win32_ia32.tar.gz +0 -0
  24. package/build/qemu/2.1.0-beta.2/koffi_win32_x64.tar.gz +0 -0
  25. package/doc/benchmarks.md +2 -2
  26. package/doc/changes.md +23 -19
  27. package/doc/conf.py +14 -1
  28. package/doc/dist/doctrees/benchmarks.doctree +0 -0
  29. package/doc/dist/doctrees/changes.doctree +0 -0
  30. package/doc/dist/doctrees/environment.pickle +0 -0
  31. package/doc/dist/doctrees/functions.doctree +0 -0
  32. package/doc/dist/doctrees/index.doctree +0 -0
  33. package/doc/dist/doctrees/types.doctree +0 -0
  34. package/doc/functions.md +76 -10
  35. package/doc/templates/badges.html +4 -0
  36. package/doc/types.md +157 -161
  37. package/package.json +2 -2
  38. package/qemu/qemu.js +1 -1
  39. package/src/abi_arm32.cc +167 -3
  40. package/src/abi_arm64.cc +196 -3
  41. package/src/abi_riscv64.cc +107 -3
  42. package/src/abi_x64_sysv.cc +114 -4
  43. package/src/abi_x64_win.cc +113 -3
  44. package/src/abi_x86.cc +156 -5
  45. package/src/call.cc +241 -26
  46. package/src/call.hh +15 -3
  47. package/src/ffi.cc +123 -34
  48. package/src/ffi.hh +19 -0
  49. package/src/index.js +4 -2
  50. package/src/parser.cc +3 -5
  51. package/src/util.cc +44 -1
  52. package/src/util.hh +4 -0
  53. package/test/async.js +1 -2
  54. package/test/callbacks.js +2 -3
  55. package/test/misc.c +21 -1
  56. package/test/raylib.js +1 -1
  57. package/test/sqlite.js +7 -7
  58. package/test/sync.js +30 -4
  59. package/build/qemu/2.0.0/koffi_darwin_arm64.tar.gz +0 -0
  60. package/build/qemu/2.0.0/koffi_darwin_x64.tar.gz +0 -0
  61. package/build/qemu/2.0.0/koffi_freebsd_arm64.tar.gz +0 -0
  62. package/build/qemu/2.0.0/koffi_freebsd_ia32.tar.gz +0 -0
  63. package/build/qemu/2.0.0/koffi_freebsd_x64.tar.gz +0 -0
  64. package/build/qemu/2.0.0/koffi_linux_arm32hf.tar.gz +0 -0
  65. package/build/qemu/2.0.0/koffi_linux_arm64.tar.gz +0 -0
  66. package/build/qemu/2.0.0/koffi_linux_ia32.tar.gz +0 -0
  67. package/build/qemu/2.0.0/koffi_linux_riscv64hf64.tar.gz +0 -0
  68. package/build/qemu/2.0.0/koffi_linux_x64.tar.gz +0 -0
  69. package/build/qemu/2.0.0/koffi_openbsd_ia32.tar.gz +0 -0
  70. package/build/qemu/2.0.0/koffi_openbsd_x64.tar.gz +0 -0
  71. package/build/qemu/2.0.0/koffi_win32_arm64.tar.gz +0 -0
  72. package/build/qemu/2.0.0/koffi_win32_ia32.tar.gz +0 -0
  73. package/build/qemu/2.0.0/koffi_win32_x64.tar.gz +0 -0
  74. package/doc/dist/html/.buildinfo +0 -4
  75. package/doc/dist/html/_sources/benchmarks.md.txt +0 -137
  76. package/doc/dist/html/_sources/changes.md.txt +0 -157
  77. package/doc/dist/html/_sources/contribute.md.txt +0 -127
  78. package/doc/dist/html/_sources/functions.md.txt +0 -355
  79. package/doc/dist/html/_sources/index.rst.txt +0 -39
  80. package/doc/dist/html/_sources/memory.md.txt +0 -32
  81. package/doc/dist/html/_sources/platforms.md.txt +0 -31
  82. package/doc/dist/html/_sources/start.md.txt +0 -100
  83. package/doc/dist/html/_sources/types.md.txt +0 -545
  84. package/doc/dist/html/_static/_sphinx_javascript_frameworks_compat.js +0 -134
  85. package/doc/dist/html/_static/basic.css +0 -932
  86. package/doc/dist/html/_static/bench_linux.png +0 -0
  87. package/doc/dist/html/_static/bench_windows.png +0 -0
  88. package/doc/dist/html/_static/custom.css +0 -22
  89. package/doc/dist/html/_static/debug.css +0 -69
  90. package/doc/dist/html/_static/doctools.js +0 -264
  91. package/doc/dist/html/_static/documentation_options.js +0 -14
  92. package/doc/dist/html/_static/file.png +0 -0
  93. package/doc/dist/html/_static/jquery-3.6.0.js +0 -10881
  94. package/doc/dist/html/_static/jquery.js +0 -2
  95. package/doc/dist/html/_static/language_data.js +0 -199
  96. package/doc/dist/html/_static/minus.png +0 -0
  97. package/doc/dist/html/_static/perf_linux_20220623.png +0 -0
  98. package/doc/dist/html/_static/perf_linux_20220623_2.png +0 -0
  99. package/doc/dist/html/_static/perf_windows_20220623.png +0 -0
  100. package/doc/dist/html/_static/perf_windows_20220623_2.png +0 -0
  101. package/doc/dist/html/_static/plus.png +0 -0
  102. package/doc/dist/html/_static/pygments.css +0 -252
  103. package/doc/dist/html/_static/scripts/furo-extensions.js +0 -0
  104. package/doc/dist/html/_static/scripts/furo.js +0 -3
  105. package/doc/dist/html/_static/scripts/furo.js.LICENSE.txt +0 -7
  106. package/doc/dist/html/_static/scripts/furo.js.map +0 -1
  107. package/doc/dist/html/_static/searchtools.js +0 -531
  108. package/doc/dist/html/_static/skeleton.css +0 -296
  109. package/doc/dist/html/_static/styles/furo-extensions.css +0 -2
  110. package/doc/dist/html/_static/styles/furo-extensions.css.map +0 -1
  111. package/doc/dist/html/_static/styles/furo.css +0 -2
  112. package/doc/dist/html/_static/styles/furo.css.map +0 -1
  113. package/doc/dist/html/_static/underscore-1.13.1.js +0 -2042
  114. package/doc/dist/html/_static/underscore.js +0 -6
  115. package/doc/dist/html/benchmarks.html +0 -568
  116. package/doc/dist/html/changes.html +0 -653
  117. package/doc/dist/html/contribute.html +0 -400
  118. package/doc/dist/html/functions.html +0 -653
  119. package/doc/dist/html/genindex.html +0 -250
  120. package/doc/dist/html/index.html +0 -356
  121. package/doc/dist/html/memory.html +0 -343
  122. package/doc/dist/html/objects.inv +0 -0
  123. package/doc/dist/html/platforms.html +0 -368
  124. package/doc/dist/html/search.html +0 -258
  125. package/doc/dist/html/searchindex.js +0 -1
  126. package/doc/dist/html/start.html +0 -381
  127. package/doc/dist/html/types.html +0 -1044
@@ -1,545 +0,0 @@
1
- # Data types
2
-
3
- ## Primitive types
4
-
5
- While the C standard allows for variation in the size of most integer types, Koffi enforces the same definition for most primitive types, listed below:
6
-
7
- JS type | C type | Bytes | Signedness | Note
8
- ----------------- | ------------------ | ----- | ---------- | ---------------------------
9
- Null | void | 0 | | Only valid as a return type
10
- Number (integer) | int8 | 1 | Signed |
11
- Number (integer) | int8_t | 1 | Signed |
12
- Number (integer) | uint8 | 1 | Unsigned |
13
- Number (integer) | uint8_t | 1 | Unsigned |
14
- Number (integer) | char | 1 | Signed |
15
- Number (integer) | uchar | 1 | Unsigned |
16
- Number (integer) | unsigned char | 1 | Unsigned |
17
- Number (integer) | char16 | 2 | Signed |
18
- Number (integer) | char16_t | 2 | Signed |
19
- Number (integer) | int16 | 2 | Signed |
20
- Number (integer) | int16_t | 2 | Signed |
21
- Number (integer) | uint16 | 2 | Unsigned |
22
- Number (integer) | uint16_t | 2 | Unsigned |
23
- Number (integer) | short | 2 | Signed |
24
- Number (integer) | unsigned short | 2 | Unsigned |
25
- Number (integer) | int32 | 4 | Signed |
26
- Number (integer) | int32_t | 4 | Signed |
27
- Number (integer) | uint32 | 4 | Unsigned |
28
- Number (integer) | uint32_t | 4 | Unsigned |
29
- Number (integer) | int | 4 | Signed |
30
- Number (integer) | uint | 4 | Unsigned |
31
- Number (integer) | unsigned int | 4 | Unsigned |
32
- Number (integer) | int64 | 8 | Signed |
33
- Number (integer) | int64_t | 8 | Signed |
34
- Number (integer) | uint64 | 8 | Unsigned |
35
- Number (integer) | uint64_t | 8 | Unsigned |
36
- Number (integer) | longlong | 8 | Signed |
37
- Number (integer) | long long | 8 | Signed |
38
- Number (integer) | ulonglong | 8 | Unsigned |
39
- Number (integer) | unsigned long long | 8 | Unsigned |
40
- Number (float) | float32 | 4 | |
41
- Number (float) | float64 | 8 | |
42
- Number (float) | float | 4 | |
43
- Number (float) | double | 8 | |
44
-
45
- Koffi also accepts BigInt values when converting from JS to C integers. If the value exceeds the range of the C type, Koffi will convert the number to an undefined value. In the reverse direction, BigInt values are automatically used when needed for big 64-bit integers.
46
-
47
- Koffi defines a few more types that can change size depending on the OS and the architecture:
48
-
49
- JS type | C type | Signedness | Note
50
- ---------------- | ---------------- | ---------- | ------------------------------------------------
51
- Boolean | bool | | Usually one byte
52
- Number (integer) | long | Signed | 4 or 8 bytes depending on platform (LP64, LLP64)
53
- Number (integer) | ulong | Unsigned | 4 or 8 bytes depending on platform (LP64, LLP64)
54
- Number (integer) | unsigned long | Unsigned | 4 or 8 bytes depending on platform (LP64, LLP64)
55
- Number (integer) | intptr | Signed | 4 or 8 bytes depending on register width
56
- Number (integer) | intptr_t | Signed | 4 or 8 bytes depending on register width
57
- Number (integer) | uintptr | Unsigned | 4 or 8 bytes depending on register width
58
- Number (integer) | uintptr_t | Unsigned | 4 or 8 bytes depending on register width
59
- String | str (string) | | JS strings are converted to and from UTF-8
60
- String | str16 (string16) | | JS strings are converted to and from UTF-16 (LE)
61
-
62
- Primitive types can be specified by name (in a string) or through `koffi.types`:
63
-
64
- ```js
65
- // These two lines do the same:
66
- let struct1 = koffi.struct({ dummy: 'long' });
67
- let struct2 = koffi.struct({ dummy: koffi.types.long });
68
- ```
69
-
70
- ## Struct types
71
-
72
- Koffi converts JS objects to C structs, and vice-versa.
73
-
74
- Unlike function declarations, as of now there is only one way to create a struct type, with the `koffi.struct()` function. This function takes two arguments: the first one is the name of the type, and the second one is an object containing the struct member names and types. You can omit the first argument to declare an anonymous struct.
75
-
76
- The following example illustrates how to declare the same struct in C and in JS with Koffi:
77
-
78
- ```c
79
- typedef struct A {
80
- int a;
81
- char b;
82
- const char *c;
83
- struct {
84
- double d1;
85
- double d2;
86
- } d;
87
- } A;
88
- ```
89
-
90
- ```js
91
- const A = koffi.struct('A', {
92
- a: 'int',
93
- b: 'char',
94
- c: 'const char *', // Koffi does not care about const, it is ignored
95
- d: koffi.struct({
96
- d1: 'double',
97
- d2: 'double'
98
- })
99
- });
100
- ```
101
-
102
- Koffi follows the C and ABI rules regarding struct alignment and padding.
103
-
104
- Once a struct is declared, you can use it by name (with a string, like you can do for primitive types) or through the value returned by the call to `koffi.struct()`. Only the latter is possible when declaring an anonymous struct.
105
-
106
- ```js
107
- // The following two function declarations are equivalent, and declare a function taking an A value and returning A
108
- const Function1 = lib.func('A Function(A value)');
109
- const Function2 = lib.func('Function', A, [A]);
110
- ```
111
-
112
- ## Pointer types
113
-
114
- In C, pointer arguments are used for differenty purposes. It is important to distinguish these use cases because Koffi provides different ways to deal with each of them:
115
-
116
- - **Struct pointers**: Use of struct pointers by C libraries fall in two cases: avoid (potentially) expensive copies, and to let the function change struct contents (output or input/output arguments).
117
- - **Opaque handles**: the library does not expose the contents of the structs, and only provides you with a pointer to it (e.g. `FILE *`). Only the functions provided by the library can do something with this pointer, in Koffi we call this a handle. This is usually done for ABI-stability reason, and to prevent library users from messing directly with library internals.
118
- - **Arrays**: in C, you dynamically-sized arrays are usually passed to functions with pointers, either NULL-terminated (or any other sentinel value) or with an additional length argument.
119
- - **Pointers to primitive types**: This is more rare, and generally used for output or input/output arguments. The Win32 API has a lot of these.
120
-
121
- ### Struct pointers
122
-
123
- The following Win32 example uses `GetCursorPos()` (with an output parameter) to retrieve and show the current cursor position.
124
-
125
- ```js
126
- const koffi = require('koffi');
127
- const lib = koffi.load('kernel32.dll');
128
-
129
- // Type declarations
130
- const POINT = koffi.struct('POINT', {
131
- x: 'long',
132
- y: 'long'
133
- });
134
-
135
- // Functions declarations
136
- const GetCursorPos = lib.func('int __stdcall GetCursorPos(_Out_ POINT *pos)');
137
-
138
- // Get and show cursor position
139
- let pos = {};
140
- if (!GetCursorPos(pos))
141
- throw new Error('Failed to get cursor position');
142
- console.log(pos);
143
- ```
144
-
145
- ### Opaque handles
146
-
147
- Many C libraries use some kind of object-oriented API, with a pair of functions dedicated to create and delete objects. An obvious example of this can be found in stdio.h, with the opaque `FILE *` pointer. You can open and close files with `fopen()` and `fclose()`, and manipule the handle with other functions such as `fread()` or `ftell()`.
148
-
149
- In Koffi, you can manage this with opaque handles. Declare the handle type with `koffi.handle(name)`, and use a pointer to this type either as a return type or some kind of [output parameter](functions.md#output-parameters) (with a double pointer).
150
-
151
- ```{note}
152
- Opaque handles **have changed in version 2.0**.
153
-
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
-
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.
159
- ```
160
-
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`.
162
-
163
- ```c
164
- // Build with: clang -fPIC -o handles.so -shared handles.c -Wall -O2
165
-
166
- #include <stdlib.h>
167
- #include <stdbool.h>
168
- #include <stdio.h>
169
- #include <errno.h>
170
- #include <string.h>
171
-
172
- typedef struct Fragment {
173
- struct Fragment *next;
174
-
175
- size_t len;
176
- char str[];
177
- } Fragment;
178
-
179
- typedef struct Concat {
180
- Fragment *first;
181
- Fragment *last;
182
-
183
- size_t total;
184
- } Concat;
185
-
186
- bool ConcatNewOut(Concat **out)
187
- {
188
- Concat *c = malloc(sizeof(*c));
189
- if (!c) {
190
- fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
191
- return false;
192
- }
193
-
194
- c->first = NULL;
195
- c->last = NULL;
196
- c->total = 0;
197
-
198
- *out = c;
199
- return true;
200
- }
201
-
202
- Concat *ConcatNew()
203
- {
204
- Concat *c = NULL;
205
- ConcatNewOut(&c);
206
- return c;
207
- }
208
-
209
- void ConcatFree(Concat *c)
210
- {
211
- if (!c)
212
- return;
213
-
214
- Fragment *f = c->first;
215
-
216
- while (f) {
217
- Fragment *next = f->next;
218
- free(f);
219
- f = next;
220
- }
221
-
222
- free(c);
223
- }
224
-
225
- bool ConcatAppend(Concat *c, const char *frag)
226
- {
227
- size_t len = strlen(frag);
228
-
229
- Fragment *f = malloc(sizeof(*f) + len + 1);
230
- if (!f) {
231
- fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
232
- return false;
233
- }
234
-
235
- f->next = NULL;
236
- if (c->last) {
237
- c->last->next = f;
238
- } else {
239
- c->first = f;
240
- }
241
- c->last = f;
242
- c->total += len;
243
-
244
- f->len = len;
245
- memcpy(f->str, frag, len);
246
- f->str[len] = 0;
247
-
248
- return true;
249
- }
250
-
251
- const char *ConcatBuild(Concat *c)
252
- {
253
- Fragment *r = malloc(sizeof(*r) + c->total + 1);
254
- if (!r) {
255
- fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
256
- return NULL;
257
- }
258
-
259
- r->next = NULL;
260
- r->len = 0;
261
-
262
- Fragment *f = c->first;
263
-
264
- while (f) {
265
- Fragment *next = f->next;
266
-
267
- memcpy(r->str + r->len, f->str, f->len);
268
- r->len += f->len;
269
-
270
- free(f);
271
- f = next;
272
- }
273
- r->str[r->len] = 0;
274
-
275
- c->first = r;
276
- c->last = r;
277
-
278
- return r->str;
279
- }
280
- ```
281
-
282
- ```js
283
- const koffi = require('koffi');
284
- const lib = koffi.load('./handles.so');
285
-
286
- const Concat = koffi.handle('Concat');
287
- const ConcatNewOut = lib.func('bool ConcatNewOut(_Out_ Concat **out)');
288
- const ConcatNew = lib.func('Concat *ConcatNew()');
289
- const ConcatFree = lib.func('void ConcatFree(Concat *c)');
290
- const ConcatAppend = lib.func('bool ConcatAppend(Concat *c, const char *frag)');
291
- const ConcatBuild = lib.func('const char *ConcatBuild(Concat *c)');
292
-
293
- let c = ConcatNew();
294
- if (!c) {
295
- // This is stupid, it does the same, but try both versions (return value, output parameter)
296
- let ptr = [null];
297
- if (!ConcatNewOut(ptr))
298
- throw new Error('Allocation failure');
299
- c = ptr[0];
300
- }
301
-
302
- try {
303
- if (!ConcatAppend(c, 'Hello... '))
304
- throw new Error('Allocation failure');
305
- if (!ConcatAppend(c, 'World!\n'))
306
- throw new Error('Allocation failure');
307
-
308
- for (let i = 1; i <= 30; i++) {
309
- let frag;
310
- if (i % 15 == 0) {
311
- frag = 'FizzBuzz';
312
- } else if (i % 5 == 0) {
313
- frag = 'Buzz';
314
- } else if (i % 3 == 0) {
315
- frag = 'Fizz';
316
- } else {
317
- frag = String(i);
318
- }
319
-
320
- if (!ConcatAppend(c, frag))
321
- throw new Error('Allocation failure');
322
- if (!ConcatAppend(c, ' '))
323
- throw new Error('Allocation failure');
324
- }
325
-
326
- let str = ConcatBuild(c);
327
- if (str == null)
328
- throw new Error('Allocation failure');
329
- console.log(str);
330
- } finally {
331
- ConcatFree(c);
332
- }
333
- ```
334
-
335
- ### Array pointers
336
-
337
- In C, dynamically-sized arrays are usually passed around as pointers. The length is either passed as an additional argument, or inferred from the array content itself, for example with a terminating sentinel value (such as a NULL pointers in the case of an array of strings).
338
-
339
- Koffi can translate JS arrays and TypedArrays to pointer arguments. However, because C does not have a proper notion of dynamically-sized arrays (fat pointers), you need to provide the length or the sentinel value yourself depending on the API.
340
-
341
- Here is a simple example of a C function taking a NULL-terminated list of strings as input, to calculate the total length of all strings.
342
-
343
- ```c
344
- // Build with: clang -fPIC -o length.so -shared length.c -Wall -O2
345
-
346
- #include <stdlib.h>
347
- #include <stdint.h>
348
- #include <string.h>
349
-
350
- int64_t ComputeTotalLength(const char **strings)
351
- {
352
- int64_t total = 0;
353
-
354
- for (const char **ptr = strings; *ptr; ptr++) {
355
- const char *str = *ptr;
356
- total += strlen(str);
357
- }
358
-
359
- return total;
360
- }
361
- ```
362
-
363
- ```js
364
- const koffi = require('koffi');
365
- const lib = koffi.load('./length.so');
366
-
367
- const ComputeTotalLength = lib.func('int64_t ComputeTotalLength(const char **strings)');
368
-
369
- let strings = ['Get', 'Total', 'Length', null];
370
- let total = ComputeTotalLength(strings);
371
-
372
- console.log(total); // Prints 14
373
- ```
374
-
375
- By default, just like for objects, array arguments are copied from JS to C but not vice-versa. You can however change the direction as documented in the section on [output parameters](functions.md#output-parameters).
376
-
377
- Here is an example based on the Win32 API, listing files in the current directory with `FindFirstFileW()` and `FindNextFileW()`:
378
-
379
- ```js
380
- const koffi = require('koffi');
381
- const lib = koffi.load('kernel32.dll');
382
-
383
- const HANDLE = koffi.pointer('HANDLE', koffi.handle());
384
- const FILETIME = koffi.struct('FILETIME', {
385
- dwLowDateTime: 'uint',
386
- dwHighDateTime: 'uint'
387
- });
388
- const WIN32_FIND_DATA = koffi.struct('WIN32_FIND_DATA', {
389
- dwFileAttributes: 'uint',
390
- ftCreationTime: FILETIME,
391
- ftLastAccessTime: FILETIME,
392
- ftLastWriteTime: FILETIME,
393
- nFileSizeHigh: 'uint',
394
- nFileSizeLow: 'uint',
395
- dwReserved0: 'uint',
396
- dwReserved1: 'uint',
397
- cFileName: koffi.array('char16', 260),
398
- cAlternateFileName: koffi.array('char16', 14),
399
- dwFileType: 'uint', // Obsolete. Do not use.
400
- dwCreatorType: 'uint', // Obsolete. Do not use
401
- wFinderFlags: 'ushort' // Obsolete. Do not use
402
- });
403
-
404
- const FindFirstFile = lib.func('HANDLE __stdcall FindFirstFileW(str16 path, _Out_ WIN32_FIND_DATA *data)');
405
- const FindNextFile = lib.func('bool __stdcall FindNextFileW(HANDLE h, _Out_ WIN32_FIND_DATA *data)');
406
- const FindClose = lib.func('bool __stdcall FindClose(HANDLE h)');
407
- const GetLastError = lib.func('uint GetLastError()');
408
-
409
- function list(dirname) {
410
- let filenames = [];
411
-
412
- let data = {};
413
- let h = FindFirstFile(dirname + '\\*', data);
414
-
415
- if (!h) {
416
- if (GetLastError() == 2) // ERROR_FILE_NOT_FOUND
417
- return filenames;
418
- throw new Error('FindFirstFile() failed');
419
- }
420
-
421
- try {
422
- do {
423
- if (data.cFileName != '.' && data.cFileName != '..')
424
- filenames.push(data.cFileName);
425
- } while (FindNextFile(h, data));
426
-
427
- if (GetLastError() != 18) // ERROR_NO_MORE_FILES
428
- throw new Error('FindNextFile() failed');
429
- } finally {
430
- FindClose(h);
431
- }
432
-
433
- return filenames;
434
- }
435
-
436
- let filenames = list('.');
437
- console.log(filenames);
438
- ```
439
-
440
- ### Pointers to primitive types
441
-
442
- In javascript, it is not possible to pass a primitive value by reference to another function. This means that you cannot call a function and expect it to modify the value of one of its number or string parameter.
443
-
444
- However, arrays and objects (among others) are reference type values. Assigning an array or an object from one variable to another does not invole any copy. Instead, as the following example illustrates, the new variable references the same array as the first:
445
-
446
- ```js
447
- let list1 = [1, 2];
448
- let list2 = list1;
449
-
450
- list2[1] = 42;
451
-
452
- console.log(list1); // Prints [1, 42]
453
- ```
454
-
455
- All of this means that C functions that are expected to modify their primitive output values (such as an `int *` parameter) cannot be used directly. However, thanks to Koffi's transparent array support, you can use Javascript arrays to approximate reference semantics with single-element arrays.
456
-
457
- Below, you can find an example of an addition function where the result is stored in an `int *` input/output parameter and how to use this function from Koffi.
458
-
459
- ```c
460
- void AddInt(int *dest, int add)
461
- {
462
- *dest += add;
463
- }
464
- ```
465
-
466
- You can simply pass a single-element array as the first argument:
467
-
468
- ```js
469
- const AddInt = lib.func('void AddInt(_Inout_ int *dest, int add)');
470
-
471
- let sum = [36];
472
- AddInt(sum, 6);
473
-
474
- console.log(sum[0]); // Prints 42
475
- ```
476
-
477
- ## Fixed-size C arrays
478
-
479
- Fixed-size arrays are declared with `koffi.array(type, length)`. Just like in C, they cannot be passed as functions parameters (they degenerate to pointers), or returned by value. You can however embed them in struct types.
480
-
481
- Koffi applies the following conversion rules when passing arrays to/from C:
482
-
483
- - **JS to C**: Koffi can take a normal Array (e.g. `[1, 2]`) or a TypedArray of the correct type (e.g. `Uint8Array` for an array of `uint8_t` numbers)
484
- - **C to JS** (return value, output parameters, callbacks): Koffi will use a TypedArray if possible. But you can change this behavior when you create the array type with the optional hint argument: `koffi.array('uint8_t', 64, 'array')`. For non-number types, such as arrays of strings or structs, Koffi creates normal arrays.
485
-
486
- See the example below:
487
-
488
- ```js
489
- const koffi = require('koffi');
490
-
491
- // Those two structs are exactly the same, only the array conversion hint is different
492
- const Foo1 = koffi.struct('Foo', {
493
- i: 'int',
494
- a16: koffi.array('int16_t', 8)
495
- });
496
- const Foo2 = koffi.struct('Foo', {
497
- i: 'int',
498
- a16: koffi.array('int16_t', 8, 'array')
499
- });
500
-
501
- // Uses an hypothetical C function that just returns the struct passed as a parameter
502
- const ReturnFoo1 = lib.func('Foo1 ReturnFoo(Foo1 p)');
503
- const ReturnFoo2 = lib.func('Foo2 ReturnFoo(Foo2 p)');
504
-
505
- console.log(ReturnFoo1({ i: 5, a16: [6, 8] })) // Prints { i: 5, a16: Int16Array(2) [6, 8] }
506
- console.log(ReturnFoo2({ i: 5, a16: [6, 8] })) // Prints { i: 5, a16: [6, 8] }
507
- ```
508
-
509
- ### Handling of strings
510
-
511
- Koffi can also convert JS strings to fixed-sized arrays in the following cases:
512
-
513
- - **char arrays** are filled with the UTF-8 encoded string, truncated if needed. The buffer is always NUL-terminated.
514
- - **char16 (or char16_t) arrays** are filled with the UTF-16 encoded string, truncated if needed. The buffer is always NUL-terminated.
515
-
516
- The reverse case is also true, Koffi can convert a C fixed-size buffer to a JS string. This happens by default for char, char16 and char16_t arrays, but you can also explicitly ask for this with the `string` array hint (e.g. `koffi.array('char', 8, 'string')`).
517
-
518
- ## Type introspection
519
-
520
- Koffi exposes three functions to explore type information:
521
-
522
- - `koffi.sizeof(type)` to get the size of a type
523
- - `koffi.alignof(type)` to get the alignment of a type
524
- - `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)
525
- - `koffi.resolve(type)` to get the resolved type object from a type string
526
-
527
- ```{note}
528
- The value returned by `introspect()` has **changed in version 2.0**.
529
-
530
- 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.
531
-
532
- Consult the [migration guide](changes.md) for more information.
533
- ```
534
-
535
- Just like before, you can refer to primitive types by their name or through `koffi.types`:
536
-
537
- ```js
538
- // These two lines do the same:
539
- console.log(koffi.sizeof('long'));
540
- console.log(koffi.sizeof(koffi.types.long));
541
- ```
542
-
543
- ## Type aliasing
544
-
545
- You can alias a type with `koffi.alias(name, type)`. Aliased types are completely equivalent.
@@ -1,134 +0,0 @@
1
- /*
2
- * _sphinx_javascript_frameworks_compat.js
3
- * ~~~~~~~~~~
4
- *
5
- * Compatability shim for jQuery and underscores.js.
6
- *
7
- * WILL BE REMOVED IN Sphinx 6.0
8
- * xref RemovedInSphinx60Warning
9
- *
10
- */
11
-
12
- /**
13
- * select a different prefix for underscore
14
- */
15
- $u = _.noConflict();
16
-
17
-
18
- /**
19
- * small helper function to urldecode strings
20
- *
21
- * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
22
- */
23
- jQuery.urldecode = function(x) {
24
- if (!x) {
25
- return x
26
- }
27
- return decodeURIComponent(x.replace(/\+/g, ' '));
28
- };
29
-
30
- /**
31
- * small helper function to urlencode strings
32
- */
33
- jQuery.urlencode = encodeURIComponent;
34
-
35
- /**
36
- * This function returns the parsed url parameters of the
37
- * current request. Multiple values per key are supported,
38
- * it will always return arrays of strings for the value parts.
39
- */
40
- jQuery.getQueryParameters = function(s) {
41
- if (typeof s === 'undefined')
42
- s = document.location.search;
43
- var parts = s.substr(s.indexOf('?') + 1).split('&');
44
- var result = {};
45
- for (var i = 0; i < parts.length; i++) {
46
- var tmp = parts[i].split('=', 2);
47
- var key = jQuery.urldecode(tmp[0]);
48
- var value = jQuery.urldecode(tmp[1]);
49
- if (key in result)
50
- result[key].push(value);
51
- else
52
- result[key] = [value];
53
- }
54
- return result;
55
- };
56
-
57
- /**
58
- * highlight a given string on a jquery object by wrapping it in
59
- * span elements with the given class name.
60
- */
61
- jQuery.fn.highlightText = function(text, className) {
62
- function highlight(node, addItems) {
63
- if (node.nodeType === 3) {
64
- var val = node.nodeValue;
65
- var pos = val.toLowerCase().indexOf(text);
66
- if (pos >= 0 &&
67
- !jQuery(node.parentNode).hasClass(className) &&
68
- !jQuery(node.parentNode).hasClass("nohighlight")) {
69
- var span;
70
- var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
71
- if (isInSVG) {
72
- span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
73
- } else {
74
- span = document.createElement("span");
75
- span.className = className;
76
- }
77
- span.appendChild(document.createTextNode(val.substr(pos, text.length)));
78
- node.parentNode.insertBefore(span, node.parentNode.insertBefore(
79
- document.createTextNode(val.substr(pos + text.length)),
80
- node.nextSibling));
81
- node.nodeValue = val.substr(0, pos);
82
- if (isInSVG) {
83
- var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
84
- var bbox = node.parentElement.getBBox();
85
- rect.x.baseVal.value = bbox.x;
86
- rect.y.baseVal.value = bbox.y;
87
- rect.width.baseVal.value = bbox.width;
88
- rect.height.baseVal.value = bbox.height;
89
- rect.setAttribute('class', className);
90
- addItems.push({
91
- "parent": node.parentNode,
92
- "target": rect});
93
- }
94
- }
95
- }
96
- else if (!jQuery(node).is("button, select, textarea")) {
97
- jQuery.each(node.childNodes, function() {
98
- highlight(this, addItems);
99
- });
100
- }
101
- }
102
- var addItems = [];
103
- var result = this.each(function() {
104
- highlight(this, addItems);
105
- });
106
- for (var i = 0; i < addItems.length; ++i) {
107
- jQuery(addItems[i].parent).before(addItems[i].target);
108
- }
109
- return result;
110
- };
111
-
112
- /*
113
- * backward compatibility for jQuery.browser
114
- * This will be supported until firefox bug is fixed.
115
- */
116
- if (!jQuery.browser) {
117
- jQuery.uaMatch = function(ua) {
118
- ua = ua.toLowerCase();
119
-
120
- var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
121
- /(webkit)[ \/]([\w.]+)/.exec(ua) ||
122
- /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
123
- /(msie) ([\w.]+)/.exec(ua) ||
124
- ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
125
- [];
126
-
127
- return {
128
- browser: match[ 1 ] || "",
129
- version: match[ 2 ] || "0"
130
- };
131
- };
132
- jQuery.browser = {};
133
- jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
134
- }