koffi 2.0.1 → 2.1.0-beta.3

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 (90) hide show
  1. package/CMakeLists.txt +2 -9
  2. package/ChangeLog.md +17 -0
  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.3/koffi_darwin_arm64.tar.gz +0 -0
  11. package/build/qemu/2.1.0-beta.3/koffi_darwin_x64.tar.gz +0 -0
  12. package/build/qemu/2.1.0-beta.3/koffi_freebsd_arm64.tar.gz +0 -0
  13. package/build/qemu/2.1.0-beta.3/koffi_freebsd_ia32.tar.gz +0 -0
  14. package/build/qemu/2.1.0-beta.3/koffi_freebsd_x64.tar.gz +0 -0
  15. package/build/qemu/2.1.0-beta.3/koffi_linux_arm32hf.tar.gz +0 -0
  16. package/build/qemu/2.1.0-beta.3/koffi_linux_arm64.tar.gz +0 -0
  17. package/build/qemu/2.1.0-beta.3/koffi_linux_ia32.tar.gz +0 -0
  18. package/build/qemu/2.1.0-beta.3/koffi_linux_riscv64hf64.tar.gz +0 -0
  19. package/build/qemu/2.1.0-beta.3/koffi_linux_x64.tar.gz +0 -0
  20. package/build/qemu/2.1.0-beta.3/koffi_openbsd_ia32.tar.gz +0 -0
  21. package/build/qemu/2.1.0-beta.3/koffi_openbsd_x64.tar.gz +0 -0
  22. package/build/qemu/2.1.0-beta.3/koffi_win32_arm64.tar.gz +0 -0
  23. package/build/qemu/2.1.0-beta.3/koffi_win32_ia32.tar.gz +0 -0
  24. package/build/qemu/2.1.0-beta.3/koffi_win32_x64.tar.gz +0 -0
  25. package/doc/Makefile +1 -1
  26. package/doc/changes.md +12 -8
  27. package/doc/conf.py +5 -0
  28. package/doc/dist/doctrees/changes.doctree +0 -0
  29. package/doc/dist/doctrees/environment.pickle +0 -0
  30. package/doc/dist/doctrees/functions.doctree +0 -0
  31. package/doc/dist/doctrees/index.doctree +0 -0
  32. package/doc/dist/doctrees/types.doctree +0 -0
  33. package/doc/dist/html/.buildinfo +1 -1
  34. package/doc/dist/html/_sources/changes.md.txt +12 -8
  35. package/doc/dist/html/_sources/functions.md.txt +71 -5
  36. package/doc/dist/html/_sources/types.md.txt +147 -159
  37. package/doc/dist/html/benchmarks.html +2 -3
  38. package/doc/dist/html/changes.html +64 -35
  39. package/doc/dist/html/contribute.html +2 -3
  40. package/doc/dist/html/functions.html +73 -12
  41. package/doc/dist/html/genindex.html +2 -3
  42. package/doc/dist/html/index.html +6 -7
  43. package/doc/dist/html/memory.html +2 -3
  44. package/doc/dist/html/objects.inv +0 -0
  45. package/doc/dist/html/platforms.html +3 -4
  46. package/doc/dist/html/search.html +2 -3
  47. package/doc/dist/html/searchindex.js +1 -1
  48. package/doc/dist/html/start.html +2 -3
  49. package/doc/dist/html/types.html +238 -237
  50. package/doc/functions.md +71 -5
  51. package/doc/make.bat +1 -1
  52. package/doc/templates/badges.html +1 -2
  53. package/doc/types.md +149 -159
  54. package/package.json +3 -2
  55. package/qemu/qemu.js +1 -1
  56. package/src/abi_arm32.cc +208 -102
  57. package/src/abi_arm64.cc +239 -55
  58. package/src/abi_riscv64.cc +128 -40
  59. package/src/abi_x64_sysv.cc +135 -41
  60. package/src/abi_x64_win.cc +134 -40
  61. package/src/abi_x86.cc +182 -67
  62. package/src/call.cc +241 -26
  63. package/src/call.hh +15 -3
  64. package/src/ffi.cc +120 -31
  65. package/src/ffi.hh +19 -0
  66. package/src/index.js +4 -2
  67. package/src/parser.cc +3 -5
  68. package/src/util.cc +44 -1
  69. package/src/util.hh +4 -0
  70. package/test/async.js +1 -2
  71. package/test/callbacks.js +2 -3
  72. package/test/misc.c +64 -1
  73. package/test/raylib.js +1 -1
  74. package/test/sqlite.js +3 -3
  75. package/test/sync.js +108 -3
  76. package/build/qemu/2.0.1/koffi_darwin_arm64.tar.gz +0 -0
  77. package/build/qemu/2.0.1/koffi_darwin_x64.tar.gz +0 -0
  78. package/build/qemu/2.0.1/koffi_freebsd_arm64.tar.gz +0 -0
  79. package/build/qemu/2.0.1/koffi_freebsd_ia32.tar.gz +0 -0
  80. package/build/qemu/2.0.1/koffi_freebsd_x64.tar.gz +0 -0
  81. package/build/qemu/2.0.1/koffi_linux_arm32hf.tar.gz +0 -0
  82. package/build/qemu/2.0.1/koffi_linux_arm64.tar.gz +0 -0
  83. package/build/qemu/2.0.1/koffi_linux_ia32.tar.gz +0 -0
  84. package/build/qemu/2.0.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  85. package/build/qemu/2.0.1/koffi_linux_x64.tar.gz +0 -0
  86. package/build/qemu/2.0.1/koffi_openbsd_ia32.tar.gz +0 -0
  87. package/build/qemu/2.0.1/koffi_openbsd_x64.tar.gz +0 -0
  88. package/build/qemu/2.0.1/koffi_win32_arm64.tar.gz +0 -0
  89. package/build/qemu/2.0.1/koffi_win32_ia32.tar.gz +0 -0
  90. package/build/qemu/2.0.1/koffi_win32_x64.tar.gz +0 -0
@@ -174,10 +174,9 @@
174
174
 
175
175
  </div>
176
176
  <div style="text-align: center; margin-top: 2em;">
177
+ <a href="https://www.npmjs.com/package/koffi"><img src="https://img.shields.io/badge/NPM-2.O.1-brightgreen" alt="NPM"/></a>
177
178
  <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>
179
- </div>
180
- </div>
179
+ </div></div>
181
180
 
182
181
  </div>
183
182
 
@@ -211,6 +210,8 @@
211
210
  <h1>Data types<a class="headerlink" href="#data-types" title="Permalink to this heading">#</a></h1>
212
211
  <section id="primitive-types">
213
212
  <h2>Primitive types<a class="headerlink" href="#primitive-types" title="Permalink to this heading">#</a></h2>
213
+ <section id="standard-types">
214
+ <h3>Standard types<a class="headerlink" href="#standard-types" title="Permalink to this heading">#</a></h3>
214
215
  <p>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:</p>
215
216
  <div class="table-wrapper colwidths-auto docutils container">
216
217
  <table class="docutils align-default">
@@ -223,32 +224,20 @@
223
224
  </tr>
224
225
  </thead>
225
226
  <tbody>
226
- <tr class="row-even"><td><p>Null</p></td>
227
+ <tr class="row-even"><td><p>Undefined</p></td>
227
228
  <td><p>void</p></td>
228
229
  <td><p>0</p></td>
229
230
  <td><p></p></td>
230
231
  <td><p>Only valid as a return type</p></td>
231
232
  </tr>
232
233
  <tr class="row-odd"><td><p>Number (integer)</p></td>
233
- <td><p>int8</p></td>
234
+ <td><p>int8, int8_t</p></td>
234
235
  <td><p>1</p></td>
235
236
  <td><p>Signed</p></td>
236
237
  <td><p></p></td>
237
238
  </tr>
238
239
  <tr class="row-even"><td><p>Number (integer)</p></td>
239
- <td><p>int8_t</p></td>
240
- <td><p>1</p></td>
241
- <td><p>Signed</p></td>
242
- <td><p></p></td>
243
- </tr>
244
- <tr class="row-odd"><td><p>Number (integer)</p></td>
245
- <td><p>uint8</p></td>
246
- <td><p>1</p></td>
247
- <td><p>Unsigned</p></td>
248
- <td><p></p></td>
249
- </tr>
250
- <tr class="row-even"><td><p>Number (integer)</p></td>
251
- <td><p>uint8_t</p></td>
240
+ <td><p>uint8, uint8_t</p></td>
252
241
  <td><p>1</p></td>
253
242
  <td><p>Unsigned</p></td>
254
243
  <td><p></p></td>
@@ -260,49 +249,25 @@
260
249
  <td><p></p></td>
261
250
  </tr>
262
251
  <tr class="row-even"><td><p>Number (integer)</p></td>
263
- <td><p>uchar</p></td>
264
- <td><p>1</p></td>
265
- <td><p>Unsigned</p></td>
266
- <td><p></p></td>
267
- </tr>
268
- <tr class="row-odd"><td><p>Number (integer)</p></td>
269
- <td><p>unsigned char</p></td>
252
+ <td><p>uchar, unsigned char</p></td>
270
253
  <td><p>1</p></td>
271
254
  <td><p>Unsigned</p></td>
272
255
  <td><p></p></td>
273
256
  </tr>
274
- <tr class="row-even"><td><p>Number (integer)</p></td>
275
- <td><p>char16</p></td>
276
- <td><p>2</p></td>
277
- <td><p>Signed</p></td>
278
- <td><p></p></td>
279
- </tr>
280
257
  <tr class="row-odd"><td><p>Number (integer)</p></td>
281
- <td><p>char16_t</p></td>
258
+ <td><p>char16, char16_t</p></td>
282
259
  <td><p>2</p></td>
283
260
  <td><p>Signed</p></td>
284
261
  <td><p></p></td>
285
262
  </tr>
286
263
  <tr class="row-even"><td><p>Number (integer)</p></td>
287
- <td><p>int16</p></td>
264
+ <td><p>int16, int16_t</p></td>
288
265
  <td><p>2</p></td>
289
266
  <td><p>Signed</p></td>
290
267
  <td><p></p></td>
291
268
  </tr>
292
269
  <tr class="row-odd"><td><p>Number (integer)</p></td>
293
- <td><p>int16_t</p></td>
294
- <td><p>2</p></td>
295
- <td><p>Signed</p></td>
296
- <td><p></p></td>
297
- </tr>
298
- <tr class="row-even"><td><p>Number (integer)</p></td>
299
- <td><p>uint16</p></td>
300
- <td><p>2</p></td>
301
- <td><p>Unsigned</p></td>
302
- <td><p></p></td>
303
- </tr>
304
- <tr class="row-odd"><td><p>Number (integer)</p></td>
305
- <td><p>uint16_t</p></td>
270
+ <td><p>uint16, uint16_t</p></td>
306
271
  <td><p>2</p></td>
307
272
  <td><p>Unsigned</p></td>
308
273
  <td><p></p></td>
@@ -314,31 +279,19 @@
314
279
  <td><p></p></td>
315
280
  </tr>
316
281
  <tr class="row-odd"><td><p>Number (integer)</p></td>
317
- <td><p>unsigned short</p></td>
282
+ <td><p>ushort, unsigned short</p></td>
318
283
  <td><p>2</p></td>
319
284
  <td><p>Unsigned</p></td>
320
285
  <td><p></p></td>
321
286
  </tr>
322
287
  <tr class="row-even"><td><p>Number (integer)</p></td>
323
- <td><p>int32</p></td>
324
- <td><p>4</p></td>
325
- <td><p>Signed</p></td>
326
- <td><p></p></td>
327
- </tr>
328
- <tr class="row-odd"><td><p>Number (integer)</p></td>
329
- <td><p>int32_t</p></td>
288
+ <td><p>int32, int32_t</p></td>
330
289
  <td><p>4</p></td>
331
290
  <td><p>Signed</p></td>
332
291
  <td><p></p></td>
333
292
  </tr>
334
- <tr class="row-even"><td><p>Number (integer)</p></td>
335
- <td><p>uint32</p></td>
336
- <td><p>4</p></td>
337
- <td><p>Unsigned</p></td>
338
- <td><p></p></td>
339
- </tr>
340
293
  <tr class="row-odd"><td><p>Number (integer)</p></td>
341
- <td><p>uint32_t</p></td>
294
+ <td><p>uint32, uint32_t</p></td>
342
295
  <td><p>4</p></td>
343
296
  <td><p>Unsigned</p></td>
344
297
  <td><p></p></td>
@@ -350,84 +303,54 @@
350
303
  <td><p></p></td>
351
304
  </tr>
352
305
  <tr class="row-odd"><td><p>Number (integer)</p></td>
353
- <td><p>uint</p></td>
306
+ <td><p>uint, unsigned int</p></td>
354
307
  <td><p>4</p></td>
355
308
  <td><p>Unsigned</p></td>
356
309
  <td><p></p></td>
357
310
  </tr>
358
311
  <tr class="row-even"><td><p>Number (integer)</p></td>
359
- <td><p>unsigned int</p></td>
360
- <td><p>4</p></td>
361
- <td><p>Unsigned</p></td>
362
- <td><p></p></td>
363
- </tr>
364
- <tr class="row-odd"><td><p>Number (integer)</p></td>
365
- <td><p>int64</p></td>
366
- <td><p>8</p></td>
367
- <td><p>Signed</p></td>
368
- <td><p></p></td>
369
- </tr>
370
- <tr class="row-even"><td><p>Number (integer)</p></td>
371
- <td><p>int64_t</p></td>
312
+ <td><p>int64, int64_t</p></td>
372
313
  <td><p>8</p></td>
373
314
  <td><p>Signed</p></td>
374
315
  <td><p></p></td>
375
316
  </tr>
376
317
  <tr class="row-odd"><td><p>Number (integer)</p></td>
377
- <td><p>uint64</p></td>
318
+ <td><p>uint64, uint64_t</p></td>
378
319
  <td><p>8</p></td>
379
320
  <td><p>Unsigned</p></td>
380
321
  <td><p></p></td>
381
322
  </tr>
382
323
  <tr class="row-even"><td><p>Number (integer)</p></td>
383
- <td><p>uint64_t</p></td>
384
- <td><p>8</p></td>
385
- <td><p>Unsigned</p></td>
386
- <td><p></p></td>
387
- </tr>
388
- <tr class="row-odd"><td><p>Number (integer)</p></td>
389
- <td><p>longlong</p></td>
390
- <td><p>8</p></td>
391
- <td><p>Signed</p></td>
392
- <td><p></p></td>
393
- </tr>
394
- <tr class="row-even"><td><p>Number (integer)</p></td>
395
- <td><p>long long</p></td>
324
+ <td><p>longlong, long long</p></td>
396
325
  <td><p>8</p></td>
397
326
  <td><p>Signed</p></td>
398
327
  <td><p></p></td>
399
328
  </tr>
400
329
  <tr class="row-odd"><td><p>Number (integer)</p></td>
401
- <td><p>ulonglong</p></td>
402
- <td><p>8</p></td>
403
- <td><p>Unsigned</p></td>
404
- <td><p></p></td>
405
- </tr>
406
- <tr class="row-even"><td><p>Number (integer)</p></td>
407
- <td><p>unsigned long long</p></td>
330
+ <td><p>ulonglong, unsigned long long</p></td>
408
331
  <td><p>8</p></td>
409
332
  <td><p>Unsigned</p></td>
410
333
  <td><p></p></td>
411
334
  </tr>
412
- <tr class="row-odd"><td><p>Number (float)</p></td>
335
+ <tr class="row-even"><td><p>Number (float)</p></td>
413
336
  <td><p>float32</p></td>
414
337
  <td><p>4</p></td>
415
338
  <td><p></p></td>
416
339
  <td><p></p></td>
417
340
  </tr>
418
- <tr class="row-even"><td><p>Number (float)</p></td>
341
+ <tr class="row-odd"><td><p>Number (float)</p></td>
419
342
  <td><p>float64</p></td>
420
343
  <td><p>8</p></td>
421
344
  <td><p></p></td>
422
345
  <td><p></p></td>
423
346
  </tr>
424
- <tr class="row-odd"><td><p>Number (float)</p></td>
347
+ <tr class="row-even"><td><p>Number (float)</p></td>
425
348
  <td><p>float</p></td>
426
349
  <td><p>4</p></td>
427
350
  <td><p></p></td>
428
351
  <td><p></p></td>
429
352
  </tr>
430
- <tr class="row-even"><td><p>Number (float)</p></td>
353
+ <tr class="row-odd"><td><p>Number (float)</p></td>
431
354
  <td><p>double</p></td>
432
355
  <td><p>8</p></td>
433
356
  <td><p></p></td>
@@ -489,12 +412,12 @@
489
412
  <td><p>4 or 8 bytes depending on register width</p></td>
490
413
  </tr>
491
414
  <tr class="row-even"><td><p>String</p></td>
492
- <td><p>str (string)</p></td>
415
+ <td><p>str, string</p></td>
493
416
  <td><p></p></td>
494
417
  <td><p>JS strings are converted to and from UTF-8</p></td>
495
418
  </tr>
496
419
  <tr class="row-odd"><td><p>String</p></td>
497
- <td><p>str16 (string16)</p></td>
420
+ <td><p>str16, string16</p></td>
498
421
  <td><p></p></td>
499
422
  <td><p>JS strings are converted to and from UTF-16 (LE)</p></td>
500
423
  </tr>
@@ -508,8 +431,101 @@
508
431
  </pre></div>
509
432
  </div>
510
433
  </section>
434
+ <section id="endian-sensitive-types">
435
+ <h3>Endian-sensitive types<a class="headerlink" href="#endian-sensitive-types" title="Permalink to this heading">#</a></h3>
436
+ <p>Koffi defines a bunch of endian-sensitive types, which can be used when dealing with binary data (network payloads, binary file formats, etc.).</p>
437
+ <div class="table-wrapper colwidths-auto docutils container">
438
+ <table class="docutils align-default">
439
+ <thead>
440
+ <tr class="row-odd"><th class="head"><p>JS type</p></th>
441
+ <th class="head"><p>C type</p></th>
442
+ <th class="head"><p>Bytes</p></th>
443
+ <th class="head"><p>Signedness</p></th>
444
+ <th class="head"><p>Endianness</p></th>
445
+ </tr>
446
+ </thead>
447
+ <tbody>
448
+ <tr class="row-even"><td><p>Number (integer)</p></td>
449
+ <td><p>int16_le, int16_le_t</p></td>
450
+ <td><p>2</p></td>
451
+ <td><p>Signed</p></td>
452
+ <td><p>Little Endian</p></td>
453
+ </tr>
454
+ <tr class="row-odd"><td><p>Number (integer)</p></td>
455
+ <td><p>int16_be, int16_be_t</p></td>
456
+ <td><p>2</p></td>
457
+ <td><p>Signed</p></td>
458
+ <td><p>Big Endian</p></td>
459
+ </tr>
460
+ <tr class="row-even"><td><p>Number (integer)</p></td>
461
+ <td><p>uint16_le, uint16_le_t</p></td>
462
+ <td><p>2</p></td>
463
+ <td><p>Unsigned</p></td>
464
+ <td><p>Little Endian</p></td>
465
+ </tr>
466
+ <tr class="row-odd"><td><p>Number (integer)</p></td>
467
+ <td><p>uint16_be, uint16_be_t</p></td>
468
+ <td><p>2</p></td>
469
+ <td><p>Unsigned</p></td>
470
+ <td><p>Big Endian</p></td>
471
+ </tr>
472
+ <tr class="row-even"><td><p>Number (integer)</p></td>
473
+ <td><p>int32_le, int32_le_t</p></td>
474
+ <td><p>4</p></td>
475
+ <td><p>Signed</p></td>
476
+ <td><p>Little Endian</p></td>
477
+ </tr>
478
+ <tr class="row-odd"><td><p>Number (integer)</p></td>
479
+ <td><p>int32_be, int32_be_t</p></td>
480
+ <td><p>4</p></td>
481
+ <td><p>Signed</p></td>
482
+ <td><p>Big Endian</p></td>
483
+ </tr>
484
+ <tr class="row-even"><td><p>Number (integer)</p></td>
485
+ <td><p>uint32_le, uint32_le_t</p></td>
486
+ <td><p>4</p></td>
487
+ <td><p>Unsigned</p></td>
488
+ <td><p>Little Endian</p></td>
489
+ </tr>
490
+ <tr class="row-odd"><td><p>Number (integer)</p></td>
491
+ <td><p>uint32_be, uint32_be_t</p></td>
492
+ <td><p>4</p></td>
493
+ <td><p>Unsigned</p></td>
494
+ <td><p>Big Endian</p></td>
495
+ </tr>
496
+ <tr class="row-even"><td><p>Number (integer)</p></td>
497
+ <td><p>int64_le, int64_le_t</p></td>
498
+ <td><p>8</p></td>
499
+ <td><p>Signed</p></td>
500
+ <td><p>Little Endian</p></td>
501
+ </tr>
502
+ <tr class="row-odd"><td><p>Number (integer)</p></td>
503
+ <td><p>int64_be, int64_be_t</p></td>
504
+ <td><p>8</p></td>
505
+ <td><p>Signed</p></td>
506
+ <td><p>Big Endian</p></td>
507
+ </tr>
508
+ <tr class="row-even"><td><p>Number (integer)</p></td>
509
+ <td><p>uint64_le, uint64_le_t</p></td>
510
+ <td><p>8</p></td>
511
+ <td><p>Unsigned</p></td>
512
+ <td><p>Little Endian</p></td>
513
+ </tr>
514
+ <tr class="row-odd"><td><p>Number (integer)</p></td>
515
+ <td><p>uint64_be, uint64_be_t</p></td>
516
+ <td><p>8</p></td>
517
+ <td><p>Unsigned</p></td>
518
+ <td><p>Big Endian</p></td>
519
+ </tr>
520
+ </tbody>
521
+ </table>
522
+ </div>
523
+ </section>
524
+ </section>
511
525
  <section id="struct-types">
512
526
  <h2>Struct types<a class="headerlink" href="#struct-types" title="Permalink to this heading">#</a></h2>
527
+ <section id="struct-definition">
528
+ <h3>Struct definition<a class="headerlink" href="#struct-definition" title="Permalink to this heading">#</a></h3>
513
529
  <p>Koffi converts JS objects to C structs, and vice-versa.</p>
514
530
  <p>Unlike function declarations, as of now there is only one way to create a struct type, with the <code class="docutils literal notranslate"><span class="pre">koffi.struct()</span></code> 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.</p>
515
531
  <p>The following example illustrates how to declare the same struct in C and in JS with Koffi:</p>
@@ -542,51 +558,38 @@
542
558
  <span class="linenos">3</span><span class="kd">const</span> <span class="nx">Function2</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;Function&#39;</span><span class="p">,</span> <span class="nx">A</span><span class="p">,</span> <span class="p">[</span><span class="nx">A</span><span class="p">]);</span>
543
559
  </pre></div>
544
560
  </div>
545
- </section>
546
- <section id="pointer-types">
547
- <h2>Pointer types<a class="headerlink" href="#pointer-types" title="Permalink to this heading">#</a></h2>
548
- <p>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:</p>
561
+ <p>Koffi automatically follows the platform C ABI regarding alignment and padding. However, you can override these rules if needed with:</p>
549
562
  <ul class="simple">
550
- <li><p><strong>Struct pointers</strong>: 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).</p></li>
551
- <li><p><strong>Opaque handles</strong>: the library does not expose the contents of the structs, and only provides you with a pointer to it (e.g. <code class="docutils literal notranslate"><span class="pre">FILE</span> <span class="pre">*</span></code>). 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.</p></li>
552
- <li><p><strong>Arrays</strong>: 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.</p></li>
553
- <li><p><strong>Pointers to primitive types</strong>: This is more rare, and generally used for output or input/output arguments. The Win32 API has a lot of these.</p></li>
563
+ <li><p>Pack all members without padding with <code class="docutils literal notranslate"><span class="pre">koffi.pack()</span></code> (instead of <code class="docutils literal notranslate"><span class="pre">koffi.struct()</span></code>)</p></li>
564
+ <li><p>Change alignment of a specific member as shown below</p></li>
554
565
  </ul>
555
- <section id="struct-pointers">
556
- <h3>Struct pointers<a class="headerlink" href="#struct-pointers" title="Permalink to this heading">#</a></h3>
557
- <p>The following Win32 example uses <code class="docutils literal notranslate"><span class="pre">GetCursorPos()</span></code> (with an output parameter) to retrieve and show the current cursor position.</p>
558
- <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
559
- <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;kernel32.dll&#39;</span><span class="p">);</span>
560
- <span class="linenos"> 3</span>
561
- <span class="linenos"> 4</span><span class="c1">// Type declarations</span>
562
- <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">POINT</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;POINT&#39;</span><span class="p">,</span> <span class="p">{</span>
563
- <span class="linenos"> 6</span> <span class="nx">x</span><span class="o">:</span> <span class="s1">&#39;long&#39;</span><span class="p">,</span>
564
- <span class="linenos"> 7</span> <span class="nx">y</span><span class="o">:</span> <span class="s1">&#39;long&#39;</span>
565
- <span class="linenos"> 8</span><span class="p">});</span>
566
- <span class="linenos"> 9</span>
567
- <span class="linenos">10</span><span class="c1">// Functions declarations</span>
568
- <span class="linenos">11</span><span class="kd">const</span> <span class="nx">GetCursorPos</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 __stdcall GetCursorPos(_Out_ POINT *pos)&#39;</span><span class="p">);</span>
569
- <span class="linenos">12</span>
570
- <span class="linenos">13</span><span class="c1">// Get and show cursor position</span>
571
- <span class="linenos">14</span><span class="kd">let</span> <span class="nx">pos</span> <span class="o">=</span> <span class="p">{};</span>
572
- <span class="linenos">15</span><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">GetCursorPos</span><span class="p">(</span><span class="nx">pos</span><span class="p">))</span>
573
- <span class="linenos">16</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 get cursor position&#39;</span><span class="p">);</span>
574
- <span class="linenos">17</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pos</span><span class="p">);</span>
566
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// This struct is 3 bytes long</span>
567
+ <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">PackedStruct</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">pack</span><span class="p">(</span><span class="s1">&#39;PackedStruct&#39;</span><span class="p">,</span> <span class="p">{</span>
568
+ <span class="linenos"> 3</span> <span class="nx">a</span><span class="o">:</span> <span class="s1">&#39;int8_t&#39;</span><span class="p">,</span>
569
+ <span class="linenos"> 4</span> <span class="nx">b</span><span class="o">:</span> <span class="s1">&#39;int16_t&#39;</span>
570
+ <span class="linenos"> 5</span><span class="p">});</span>
571
+ <span class="linenos"> 6</span>
572
+ <span class="linenos"> 7</span><span class="c1">// This one is 18 bytes long, the second member has an alignment requirement of 16 bytes</span>
573
+ <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">BigStruct</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;BigStruct&#39;</span><span class="p">,</span> <span class="p">{</span>
574
+ <span class="linenos"> 9</span> <span class="nx">a</span><span class="o">:</span> <span class="s1">&#39;int8_t&#39;</span><span class="p">,</span>
575
+ <span class="linenos">10</span> <span class="nx">b</span><span class="o">:</span> <span class="p">[</span><span class="mf">16</span><span class="p">,</span> <span class="s1">&#39;int16_t&#39;</span><span class="p">]</span>
576
+ <span class="linenos">11</span><span class="p">})</span>
575
577
  </pre></div>
576
578
  </div>
577
579
  </section>
578
- <section id="opaque-handles">
579
- <h3>Opaque handles<a class="headerlink" href="#opaque-handles" title="Permalink to this heading">#</a></h3>
580
- <p>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 <code class="docutils literal notranslate"><span class="pre">FILE</span> <span class="pre">*</span></code> pointer. You can open and close files with <code class="docutils literal notranslate"><span class="pre">fopen()</span></code> and <code class="docutils literal notranslate"><span class="pre">fclose()</span></code>, and manipule the handle with other functions such as <code class="docutils literal notranslate"><span class="pre">fread()</span></code> or <code class="docutils literal notranslate"><span class="pre">ftell()</span></code>.</p>
581
- <p>In Koffi, you can manage this with opaque handles. Declare the handle type with <code class="docutils literal notranslate"><span class="pre">koffi.handle(name)</span></code>, and use a pointer to this type either as a return type or some kind of <a class="reference internal" href="functions#output-parameters"><span class="std std-doc">output parameter</span></a> (with a double pointer).</p>
580
+ <section id="opaque-types">
581
+ <h3>Opaque types<a class="headerlink" href="#opaque-types" title="Permalink to this heading">#</a></h3>
582
+ <p>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 <code class="docutils literal notranslate"><span class="pre">FILE</span> <span class="pre">*</span></code> pointer. You can open and close files with <code class="docutils literal notranslate"><span class="pre">fopen()</span></code> and <code class="docutils literal notranslate"><span class="pre">fclose()</span></code>, and manipule the opaque pointer with other functions such as <code class="docutils literal notranslate"><span class="pre">fread()</span></code> or <code class="docutils literal notranslate"><span class="pre">ftell()</span></code>.</p>
583
+ <p>In Koffi, you can manage this with opaque types. Declare the opaque type with <code class="docutils literal notranslate"><span class="pre">koffi.opaque(name)</span></code>, and use a pointer to this type either as a return type or some kind of <a class="reference internal" href="functions#output-parameters"><span class="std std-doc">output parameter</span></a> (with a double pointer).</p>
582
584
  <div class="admonition note">
583
585
  <p class="admonition-title">Note</p>
584
- <p>Opaque handles <strong>have changed in version 2.0</strong>.</p>
586
+ <p>Opaque types <strong>have changed in version 2.0, and again in version 2.1</strong>.</p>
585
587
  <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.</p>
586
588
  <p>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 <code class="docutils literal notranslate"><span class="pre">ConcatNewOut</span></code> in the JS part), and is described in the section on <a class="reference internal" href="functions#output-parameters"><span class="std std-doc">output parameters</span></a>.</p>
589
+ <p>In addition to this, you should use <code class="docutils literal notranslate"><span class="pre">koffi.opaque()</span></code> (introduced in Koffi 2.1) instead of <code class="docutils literal notranslate"><span class="pre">koffi.handle()</span></code> which is deprecated, and will be removed eventually in Koffi 3.0.</p>
587
590
  <p>Consult the <a class="reference internal" href="changes"><span class="doc std std-doc">migration guide</span></a> for more information.</p>
588
591
  </div>
589
- <p>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: <code class="docutils literal notranslate"><span class="pre">ConcatNew</span></code> (or <code class="docutils literal notranslate"><span class="pre">ConcatNewOut</span></code>) and <code class="docutils literal notranslate"><span class="pre">ConcatFree</span></code>.</p>
592
+ <p>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 type, and is created and destroyed using a pair of C functions: <code class="docutils literal notranslate"><span class="pre">ConcatNew</span></code> (or <code class="docutils literal notranslate"><span class="pre">ConcatNewOut</span></code>) and <code class="docutils literal notranslate"><span class="pre">ConcatFree</span></code>.</p>
590
593
  <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Build with: clang -fPIC -o handles.so -shared handles.c -Wall -O2</span>
591
594
  <span class="linenos"> 2</span>
592
595
  <span class="linenos"> 3</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span>
@@ -708,7 +711,7 @@
708
711
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
709
712
  <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;./handles.so&#39;</span><span class="p">);</span>
710
713
  <span class="linenos"> 3</span>
711
- <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">Concat</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;Concat&#39;</span><span class="p">);</span>
714
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">Concat</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">opaque</span><span class="p">(</span><span class="s1">&#39;Concat&#39;</span><span class="p">);</span>
712
715
  <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">ConcatNewOut</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;bool ConcatNewOut(_Out_ Concat **out)&#39;</span><span class="p">);</span>
713
716
  <span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">ConcatNew</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;Concat *ConcatNew()&#39;</span><span class="p">);</span>
714
717
  <span class="linenos"> 7</span><span class="kd">const</span> <span class="nx">ConcatFree</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;void ConcatFree(Concat *c)&#39;</span><span class="p">);</span>
@@ -758,101 +761,48 @@
758
761
  </pre></div>
759
762
  </div>
760
763
  </section>
761
- <section id="array-pointers">
762
- <h3>Array pointers<a class="headerlink" href="#array-pointers" title="Permalink to this heading">#</a></h3>
763
- <p>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).</p>
764
- <p>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.</p>
765
- <p>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.</p>
766
- <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Build with: clang -fPIC -o length.so -shared length.c -Wall -O2</span>
767
- <span class="linenos"> 2</span>
768
- <span class="linenos"> 3</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span>
769
- <span class="linenos"> 4</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdint.h&gt;</span><span class="cp"></span>
770
- <span class="linenos"> 5</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
771
- <span class="linenos"> 6</span>
772
- <span class="linenos"> 7</span><span class="kt">int64_t</span><span class="w"> </span><span class="nf">ComputeTotalLength</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">strings</span><span class="p">)</span><span class="w"></span>
773
- <span class="linenos"> 8</span><span class="p">{</span><span class="w"></span>
774
- <span class="linenos"> 9</span><span class="w"> </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
775
- <span class="linenos">10</span>
776
- <span class="linenos">11</span><span class="w"> </span><span class="k">for</span><span class="w"> </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">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">strings</span><span class="p">;</span><span class="w"> </span><span class="o">*</span><span class="n">ptr</span><span class="p">;</span><span class="w"> </span><span class="n">ptr</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
777
- <span class="linenos">12</span><span class="w"> </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="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="n">ptr</span><span class="p">;</span><span class="w"></span>
778
- <span class="linenos">13</span><span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">strlen</span><span class="p">(</span><span class="n">str</span><span class="p">);</span><span class="w"></span>
779
- <span class="linenos">14</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
780
- <span class="linenos">15</span>
781
- <span class="linenos">16</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">total</span><span class="p">;</span><span class="w"></span>
782
- <span class="linenos">17</span><span class="p">}</span><span class="w"></span>
783
- </pre></div>
784
- </div>
785
- <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
786
- <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;./length.so&#39;</span><span class="p">);</span>
787
- <span class="linenos">3</span>
788
- <span class="linenos">4</span><span class="kd">const</span> <span class="nx">ComputeTotalLength</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;int64_t ComputeTotalLength(const char **strings)&#39;</span><span class="p">);</span>
789
- <span class="linenos">5</span>
790
- <span class="linenos">6</span><span class="kd">let</span> <span class="nx">strings</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;Get&#39;</span><span class="p">,</span> <span class="s1">&#39;Total&#39;</span><span class="p">,</span> <span class="s1">&#39;Length&#39;</span><span class="p">,</span> <span class="kc">null</span><span class="p">];</span>
791
- <span class="linenos">7</span><span class="kd">let</span> <span class="nx">total</span> <span class="o">=</span> <span class="nx">ComputeTotalLength</span><span class="p">(</span><span class="nx">strings</span><span class="p">);</span>
792
- <span class="linenos">8</span>
793
- <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">total</span><span class="p">);</span> <span class="c1">// Prints 14</span>
794
- </pre></div>
795
- </div>
796
- <p>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 <a class="reference internal" href="functions#output-parameters"><span class="std std-doc">output parameters</span></a>.</p>
797
- <p>Here is an example based on the Win32 API, listing files in the current directory with <code class="docutils literal notranslate"><span class="pre">FindFirstFileW()</span></code> and <code class="docutils literal notranslate"><span class="pre">FindNextFileW()</span></code>:</p>
764
+ </section>
765
+ <section id="pointer-types">
766
+ <h2>Pointer types<a class="headerlink" href="#pointer-types" title="Permalink to this heading">#</a></h2>
767
+ <p>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:</p>
768
+ <ul class="simple">
769
+ <li><p><strong>Struct pointers</strong>: 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).</p></li>
770
+ <li><p><strong>Opaque pointers</strong>: the library does not expose the contents of the structs, and only provides you with a pointer to it (e.g. <code class="docutils literal notranslate"><span class="pre">FILE</span> <span class="pre">*</span></code>). Only the functions provided by the library can do something with this pointer, in Koffi we call this an opaque type. This is usually done for ABI-stability reason, and to prevent library users from messing directly with library internals.</p></li>
771
+ <li><p><strong>Pointers to primitive types</strong>: This is more rare, and generally used for output or input/output arguments. The Win32 API has a lot of these.</p></li>
772
+ <li><p><strong>Arrays</strong>: 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.</p></li>
773
+ </ul>
774
+ <section id="struct-pointers">
775
+ <h3>Struct pointers<a class="headerlink" href="#struct-pointers" title="Permalink to this heading">#</a></h3>
776
+ <p>The following Win32 example uses <code class="docutils literal notranslate"><span class="pre">GetCursorPos()</span></code> (with an output parameter) to retrieve and show the current cursor position.</p>
798
777
  <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
799
778
  <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;kernel32.dll&#39;</span><span class="p">);</span>
800
779
  <span class="linenos"> 3</span>
801
- <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">HANDLE</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="s1">&#39;HANDLE&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">handle</span><span class="p">());</span>
802
- <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">FILETIME</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;FILETIME&#39;</span><span class="p">,</span> <span class="p">{</span>
803
- <span class="linenos"> 6</span> <span class="nx">dwLowDateTime</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span>
804
- <span class="linenos"> 7</span> <span class="nx">dwHighDateTime</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span>
780
+ <span class="linenos"> 4</span><span class="c1">// Type declarations</span>
781
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">POINT</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;POINT&#39;</span><span class="p">,</span> <span class="p">{</span>
782
+ <span class="linenos"> 6</span> <span class="nx">x</span><span class="o">:</span> <span class="s1">&#39;long&#39;</span><span class="p">,</span>
783
+ <span class="linenos"> 7</span> <span class="nx">y</span><span class="o">:</span> <span class="s1">&#39;long&#39;</span>
805
784
  <span class="linenos"> 8</span><span class="p">});</span>
806
- <span class="linenos"> 9</span><span class="kd">const</span> <span class="nx">WIN32_FIND_DATA</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;WIN32_FIND_DATA&#39;</span><span class="p">,</span> <span class="p">{</span>
807
- <span class="linenos">10</span> <span class="nx">dwFileAttributes</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span>
808
- <span class="linenos">11</span> <span class="nx">ftCreationTime</span><span class="o">:</span> <span class="nx">FILETIME</span><span class="p">,</span>
809
- <span class="linenos">12</span> <span class="nx">ftLastAccessTime</span><span class="o">:</span> <span class="nx">FILETIME</span><span class="p">,</span>
810
- <span class="linenos">13</span> <span class="nx">ftLastWriteTime</span><span class="o">:</span> <span class="nx">FILETIME</span><span class="p">,</span>
811
- <span class="linenos">14</span> <span class="nx">nFileSizeHigh</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span>
812
- <span class="linenos">15</span> <span class="nx">nFileSizeLow</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span>
813
- <span class="linenos">16</span> <span class="nx">dwReserved0</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span>
814
- <span class="linenos">17</span> <span class="nx">dwReserved1</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span>
815
- <span class="linenos">18</span> <span class="nx">cFileName</span><span class="o">:</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">array</span><span class="p">(</span><span class="s1">&#39;char16&#39;</span><span class="p">,</span> <span class="mf">260</span><span class="p">),</span>
816
- <span class="linenos">19</span> <span class="nx">cAlternateFileName</span><span class="o">:</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">array</span><span class="p">(</span><span class="s1">&#39;char16&#39;</span><span class="p">,</span> <span class="mf">14</span><span class="p">),</span>
817
- <span class="linenos">20</span> <span class="nx">dwFileType</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span> <span class="c1">// Obsolete. Do not use.</span>
818
- <span class="linenos">21</span> <span class="nx">dwCreatorType</span><span class="o">:</span> <span class="s1">&#39;uint&#39;</span><span class="p">,</span> <span class="c1">// Obsolete. Do not use</span>
819
- <span class="linenos">22</span> <span class="nx">wFinderFlags</span><span class="o">:</span> <span class="s1">&#39;ushort&#39;</span> <span class="c1">// Obsolete. Do not use</span>
820
- <span class="linenos">23</span><span class="p">});</span>
821
- <span class="linenos">24</span>
822
- <span class="linenos">25</span><span class="kd">const</span> <span class="nx">FindFirstFile</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;HANDLE __stdcall FindFirstFileW(str16 path, _Out_ WIN32_FIND_DATA *data)&#39;</span><span class="p">);</span>
823
- <span class="linenos">26</span><span class="kd">const</span> <span class="nx">FindNextFile</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;bool __stdcall FindNextFileW(HANDLE h, _Out_ WIN32_FIND_DATA *data)&#39;</span><span class="p">);</span>
824
- <span class="linenos">27</span><span class="kd">const</span> <span class="nx">FindClose</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;bool __stdcall FindClose(HANDLE h)&#39;</span><span class="p">);</span>
825
- <span class="linenos">28</span><span class="kd">const</span> <span class="nx">GetLastError</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;uint GetLastError()&#39;</span><span class="p">);</span>
826
- <span class="linenos">29</span>
827
- <span class="linenos">30</span><span class="kd">function</span> <span class="nx">list</span><span class="p">(</span><span class="nx">dirname</span><span class="p">)</span> <span class="p">{</span>
828
- <span class="linenos">31</span> <span class="kd">let</span> <span class="nx">filenames</span> <span class="o">=</span> <span class="p">[];</span>
829
- <span class="linenos">32</span>
830
- <span class="linenos">33</span> <span class="kd">let</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{};</span>
831
- <span class="linenos">34</span> <span class="kd">let</span> <span class="nx">h</span> <span class="o">=</span> <span class="nx">FindFirstFile</span><span class="p">(</span><span class="nx">dirname</span> <span class="o">+</span> <span class="s1">&#39;\\*&#39;</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
832
- <span class="linenos">35</span>
833
- <span class="linenos">36</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">h</span><span class="p">)</span> <span class="p">{</span>
834
- <span class="linenos">37</span> <span class="k">if</span> <span class="p">(</span><span class="nx">GetLastError</span><span class="p">()</span> <span class="o">==</span> <span class="mf">2</span><span class="p">)</span> <span class="c1">// ERROR_FILE_NOT_FOUND</span>
835
- <span class="linenos">38</span> <span class="k">return</span> <span class="nx">filenames</span><span class="p">;</span>
836
- <span class="linenos">39</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;FindFirstFile() failed&#39;</span><span class="p">);</span>
837
- <span class="linenos">40</span> <span class="p">}</span>
838
- <span class="linenos">41</span>
839
- <span class="linenos">42</span> <span class="k">try</span> <span class="p">{</span>
840
- <span class="linenos">43</span> <span class="k">do</span> <span class="p">{</span>
841
- <span class="linenos">44</span> <span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">cFileName</span> <span class="o">!=</span> <span class="s1">&#39;.&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">data</span><span class="p">.</span><span class="nx">cFileName</span> <span class="o">!=</span> <span class="s1">&#39;..&#39;</span><span class="p">)</span>
842
- <span class="linenos">45</span> <span class="nx">filenames</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">cFileName</span><span class="p">);</span>
843
- <span class="linenos">46</span> <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="nx">FindNextFile</span><span class="p">(</span><span class="nx">h</span><span class="p">,</span> <span class="nx">data</span><span class="p">));</span>
844
- <span class="linenos">47</span>
845
- <span class="linenos">48</span> <span class="k">if</span> <span class="p">(</span><span class="nx">GetLastError</span><span class="p">()</span> <span class="o">!=</span> <span class="mf">18</span><span class="p">)</span> <span class="c1">// ERROR_NO_MORE_FILES</span>
846
- <span class="linenos">49</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;FindNextFile() failed&#39;</span><span class="p">);</span>
847
- <span class="linenos">50</span> <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
848
- <span class="linenos">51</span> <span class="nx">FindClose</span><span class="p">(</span><span class="nx">h</span><span class="p">);</span>
849
- <span class="linenos">52</span> <span class="p">}</span>
850
- <span class="linenos">53</span>
851
- <span class="linenos">54</span> <span class="k">return</span> <span class="nx">filenames</span><span class="p">;</span>
852
- <span class="linenos">55</span><span class="p">}</span>
853
- <span class="linenos">56</span>
854
- <span class="linenos">57</span><span class="kd">let</span> <span class="nx">filenames</span> <span class="o">=</span> <span class="nx">list</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">);</span>
855
- <span class="linenos">58</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">filenames</span><span class="p">);</span>
785
+ <span class="linenos"> 9</span>
786
+ <span class="linenos">10</span><span class="c1">// Functions declarations</span>
787
+ <span class="linenos">11</span><span class="kd">const</span> <span class="nx">GetCursorPos</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 __stdcall GetCursorPos(_Out_ POINT *pos)&#39;</span><span class="p">);</span>
788
+ <span class="linenos">12</span>
789
+ <span class="linenos">13</span><span class="c1">// Get and show cursor position</span>
790
+ <span class="linenos">14</span><span class="kd">let</span> <span class="nx">pos</span> <span class="o">=</span> <span class="p">{};</span>
791
+ <span class="linenos">15</span><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">GetCursorPos</span><span class="p">(</span><span class="nx">pos</span><span class="p">))</span>
792
+ <span class="linenos">16</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 get cursor position&#39;</span><span class="p">);</span>
793
+ <span class="linenos">17</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pos</span><span class="p">);</span>
794
+ </pre></div>
795
+ </div>
796
+ </section>
797
+ <section id="named-pointer-types">
798
+ <h3>Named pointer types<a class="headerlink" href="#named-pointer-types" title="Permalink to this heading">#</a></h3>
799
+ <p><em>New in Koffi 2.0</em></p>
800
+ <p>Some C libraries use handles, which behave as pointers to opaque structs. An example of this is the HANDLE type in the Win32 API. If you want to reproduce this behavior, you can define a <strong>named pointer type</strong> to an opaque type, like so:</p>
801
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">HANDLE</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="s1">&#39;HANDLE&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">opaque</span><span class="p">());</span>
802
+ <span class="linenos">2</span>
803
+ <span class="linenos">3</span><span class="c1">// And now you get to use it this way:</span>
804
+ <span class="linenos">4</span><span class="kd">const</span> <span class="nx">GetHandleInformation</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;bool __stdcall GetHandleInformation(HANDLE h, _Out_ uint32_t *flags)&#39;</span><span class="p">);</span>
805
+ <span class="linenos">5</span><span class="kd">const</span> <span class="nx">CloseHandle</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;bool __stdcall CloseHandle(HANDLE h)&#39;</span><span class="p">);</span>
856
806
  </pre></div>
857
807
  </div>
858
808
  </section>
@@ -887,8 +837,10 @@
887
837
  </div>
888
838
  </section>
889
839
  </section>
840
+ <section id="array-types">
841
+ <h2>Array types<a class="headerlink" href="#array-types" title="Permalink to this heading">#</a></h2>
890
842
  <section id="fixed-size-c-arrays">
891
- <h2>Fixed-size C arrays<a class="headerlink" href="#fixed-size-c-arrays" title="Permalink to this heading">#</a></h2>
843
+ <h3>Fixed-size C arrays<a class="headerlink" href="#fixed-size-c-arrays" title="Permalink to this heading">#</a></h3>
892
844
  <p>Fixed-size arrays are declared with <code class="docutils literal notranslate"><span class="pre">koffi.array(type,</span> <span class="pre">length)</span></code>. 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.</p>
893
845
  <p>Koffi applies the following conversion rules when passing arrays to/from C:</p>
894
846
  <ul class="simple">
@@ -916,8 +868,9 @@
916
868
  <span class="linenos">18</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">ReturnFoo2</span><span class="p">({</span> <span class="nx">i</span><span class="o">:</span> <span class="mf">5</span><span class="p">,</span> <span class="nx">a16</span><span class="o">:</span> <span class="p">[</span><span class="mf">6</span><span class="p">,</span> <span class="mf">8</span><span class="p">]</span> <span class="p">}))</span> <span class="c1">// Prints { i: 5, a16: [6, 8] }</span>
917
869
  </pre></div>
918
870
  </div>
919
- <section id="handling-of-strings">
920
- <h3>Handling of strings<a class="headerlink" href="#handling-of-strings" title="Permalink to this heading">#</a></h3>
871
+ </section>
872
+ <section id="fixed-size-string-buffers">
873
+ <h3>Fixed-size string buffers<a class="headerlink" href="#fixed-size-string-buffers" title="Permalink to this heading">#</a></h3>
921
874
  <p>Koffi can also convert JS strings to fixed-sized arrays in the following cases:</p>
922
875
  <ul class="simple">
923
876
  <li><p><strong>char arrays</strong> are filled with the UTF-8 encoded string, truncated if needed. The buffer is always NUL-terminated.</p></li>
@@ -925,6 +878,43 @@
925
878
  </ul>
926
879
  <p>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 <code class="docutils literal notranslate"><span class="pre">string</span></code> array hint (e.g. <code class="docutils literal notranslate"><span class="pre">koffi.array('char',</span> <span class="pre">8,</span> <span class="pre">'string')</span></code>).</p>
927
880
  </section>
881
+ <section id="array-pointers-dynamic-arrays">
882
+ <h3>Array pointers (dynamic arrays)<a class="headerlink" href="#array-pointers-dynamic-arrays" title="Permalink to this heading">#</a></h3>
883
+ <p>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).</p>
884
+ <p>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.</p>
885
+ <p>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.</p>
886
+ <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Build with: clang -fPIC -o length.so -shared length.c -Wall -O2</span>
887
+ <span class="linenos"> 2</span>
888
+ <span class="linenos"> 3</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span>
889
+ <span class="linenos"> 4</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdint.h&gt;</span><span class="cp"></span>
890
+ <span class="linenos"> 5</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
891
+ <span class="linenos"> 6</span>
892
+ <span class="linenos"> 7</span><span class="kt">int64_t</span><span class="w"> </span><span class="nf">ComputeTotalLength</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">strings</span><span class="p">)</span><span class="w"></span>
893
+ <span class="linenos"> 8</span><span class="p">{</span><span class="w"></span>
894
+ <span class="linenos"> 9</span><span class="w"> </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
895
+ <span class="linenos">10</span>
896
+ <span class="linenos">11</span><span class="w"> </span><span class="k">for</span><span class="w"> </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">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">strings</span><span class="p">;</span><span class="w"> </span><span class="o">*</span><span class="n">ptr</span><span class="p">;</span><span class="w"> </span><span class="n">ptr</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
897
+ <span class="linenos">12</span><span class="w"> </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="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="n">ptr</span><span class="p">;</span><span class="w"></span>
898
+ <span class="linenos">13</span><span class="w"> </span><span class="n">total</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">strlen</span><span class="p">(</span><span class="n">str</span><span class="p">);</span><span class="w"></span>
899
+ <span class="linenos">14</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
900
+ <span class="linenos">15</span>
901
+ <span class="linenos">16</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">total</span><span class="p">;</span><span class="w"></span>
902
+ <span class="linenos">17</span><span class="p">}</span><span class="w"></span>
903
+ </pre></div>
904
+ </div>
905
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
906
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;./length.so&#39;</span><span class="p">);</span>
907
+ <span class="linenos">3</span>
908
+ <span class="linenos">4</span><span class="kd">const</span> <span class="nx">ComputeTotalLength</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;int64_t ComputeTotalLength(const char **strings)&#39;</span><span class="p">);</span>
909
+ <span class="linenos">5</span>
910
+ <span class="linenos">6</span><span class="kd">let</span> <span class="nx">strings</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;Get&#39;</span><span class="p">,</span> <span class="s1">&#39;Total&#39;</span><span class="p">,</span> <span class="s1">&#39;Length&#39;</span><span class="p">,</span> <span class="kc">null</span><span class="p">];</span>
911
+ <span class="linenos">7</span><span class="kd">let</span> <span class="nx">total</span> <span class="o">=</span> <span class="nx">ComputeTotalLength</span><span class="p">(</span><span class="nx">strings</span><span class="p">);</span>
912
+ <span class="linenos">8</span>
913
+ <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">total</span><span class="p">);</span> <span class="c1">// Prints 14</span>
914
+ </pre></div>
915
+ </div>
916
+ <p>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 <a class="reference internal" href="functions#output-parameters"><span class="std std-doc">output parameters</span></a>.</p>
917
+ </section>
928
918
  </section>
929
919
  <section id="disposable-types">
930
920
  <h2>Disposable types<a class="headerlink" href="#disposable-types" title="Permalink to this heading">#</a></h2>
@@ -935,6 +925,7 @@
935
925
  <h2>Utility functions<a class="headerlink" href="#utility-functions" title="Permalink to this heading">#</a></h2>
936
926
  <section id="type-introspection">
937
927
  <h3>Type introspection<a class="headerlink" href="#type-introspection" title="Permalink to this heading">#</a></h3>
928
+ <p><em>New in Koffi 2.0: <code class="docutils literal notranslate"><span class="pre">koffi.resolve()</span></code></em></p>
938
929
  <p>Koffi exposes three functions to explore type information:</p>
939
930
  <ul class="simple">
940
931
  <li><p><code class="docutils literal notranslate"><span class="pre">koffi.sizeof(type)</span></code> to get the size of a type</p></li>
@@ -957,6 +948,7 @@
957
948
  </section>
958
949
  <section id="type-aliases">
959
950
  <h3>Type aliases<a class="headerlink" href="#type-aliases" title="Permalink to this heading">#</a></h3>
951
+ <p><em>New in Koffi 2.0</em></p>
960
952
  <p>You can alias a type with <code class="docutils literal notranslate"><span class="pre">koffi.alias(name,</span> <span class="pre">type)</span></code>. Aliased types are completely equivalent.</p>
961
953
  </section>
962
954
  </section>
@@ -1020,17 +1012,26 @@
1020
1012
  <div class="toc-tree">
1021
1013
  <ul>
1022
1014
  <li><a class="reference internal" href="#">Data types</a><ul>
1023
- <li><a class="reference internal" href="#primitive-types">Primitive types</a></li>
1024
- <li><a class="reference internal" href="#struct-types">Struct types</a></li>
1015
+ <li><a class="reference internal" href="#primitive-types">Primitive types</a><ul>
1016
+ <li><a class="reference internal" href="#standard-types">Standard types</a></li>
1017
+ <li><a class="reference internal" href="#endian-sensitive-types">Endian-sensitive types</a></li>
1018
+ </ul>
1019
+ </li>
1020
+ <li><a class="reference internal" href="#struct-types">Struct types</a><ul>
1021
+ <li><a class="reference internal" href="#struct-definition">Struct definition</a></li>
1022
+ <li><a class="reference internal" href="#opaque-types">Opaque types</a></li>
1023
+ </ul>
1024
+ </li>
1025
1025
  <li><a class="reference internal" href="#pointer-types">Pointer types</a><ul>
1026
1026
  <li><a class="reference internal" href="#struct-pointers">Struct pointers</a></li>
1027
- <li><a class="reference internal" href="#opaque-handles">Opaque handles</a></li>
1028
- <li><a class="reference internal" href="#array-pointers">Array pointers</a></li>
1027
+ <li><a class="reference internal" href="#named-pointer-types">Named pointer types</a></li>
1029
1028
  <li><a class="reference internal" href="#pointers-to-primitive-types">Pointers to primitive types</a></li>
1030
1029
  </ul>
1031
1030
  </li>
1032
- <li><a class="reference internal" href="#fixed-size-c-arrays">Fixed-size C arrays</a><ul>
1033
- <li><a class="reference internal" href="#handling-of-strings">Handling of strings</a></li>
1031
+ <li><a class="reference internal" href="#array-types">Array types</a><ul>
1032
+ <li><a class="reference internal" href="#fixed-size-c-arrays">Fixed-size C arrays</a></li>
1033
+ <li><a class="reference internal" href="#fixed-size-string-buffers">Fixed-size string buffers</a></li>
1034
+ <li><a class="reference internal" href="#array-pointers-dynamic-arrays">Array pointers (dynamic arrays)</a></li>
1034
1035
  </ul>
1035
1036
  </li>
1036
1037
  <li><a class="reference internal" href="#disposable-types">Disposable types</a></li>