koffi 2.9.1 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/CHANGELOG.md +61 -48
  2. package/build/koffi/darwin_arm64/koffi.node +0 -0
  3. package/build/koffi/darwin_x64/koffi.node +0 -0
  4. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  5. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  6. package/build/koffi/freebsd_x64/koffi.node +0 -0
  7. package/build/koffi/linux_arm32/koffi.node +0 -0
  8. package/build/koffi/linux_arm64/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_riscv64/koffi.node +0 -0
  11. package/build/koffi/linux_x64/koffi.node +0 -0
  12. package/build/koffi/musl_x64/koffi.node +0 -0
  13. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  14. package/build/koffi/openbsd_x64/koffi.node +0 -0
  15. package/build/koffi/win32_arm64/koffi.node +0 -0
  16. package/build/koffi/win32_ia32/koffi.node +0 -0
  17. package/build/koffi/win32_x64/koffi.node +0 -0
  18. package/doc/README.md +27 -0
  19. package/doc/assets.ini +19 -0
  20. package/doc/develop.sh +14 -0
  21. package/doc/flaat/flaat.css +25 -0
  22. package/doc/flaat/flaat.js +150 -0
  23. package/doc/flaat/normal.css +335 -0
  24. package/doc/flaat/print.css +30 -0
  25. package/doc/flaat/small.css +101 -0
  26. package/doc/{benchmarks.md → pages/benchmarks.md} +14 -18
  27. package/doc/{callbacks.md → pages/callbacks.md} +27 -36
  28. package/doc/{contribute.md → pages/contribute.md} +10 -12
  29. package/doc/{functions.md → pages/functions.md} +29 -34
  30. package/doc/pages/index.md +20 -0
  31. package/doc/{input.md → pages/input.md} +28 -33
  32. package/doc/{migration.md → pages/migration.md} +7 -10
  33. package/doc/{misc.md → pages/misc.md} +54 -23
  34. package/doc/{output.md → pages/output.md} +17 -20
  35. package/doc/{packaging.md → pages/packaging.md} +19 -12
  36. package/doc/{platforms.md → pages/platforms.md} +25 -11
  37. package/doc/{pointers.md → pages/pointers.md} +13 -16
  38. package/doc/{start.md → pages/start.md} +12 -14
  39. package/doc/{unions.md → pages/unions.md} +5 -7
  40. package/doc/{variables.md → pages/variables.md} +7 -11
  41. package/doc/pages.ini +89 -0
  42. package/doc/static/koffi.css +21 -0
  43. package/doc/static/koffi.js +21 -0
  44. package/doc/static/koffi.png +0 -0
  45. package/doc/static/logo.webp +0 -0
  46. package/doc/static/print.css +22 -0
  47. package/doc/templates/page.html +48 -0
  48. package/index.js +2 -2
  49. package/indirect.js +2 -2
  50. package/package.json +2 -2
  51. package/src/koffi/CMakeLists.txt +6 -0
  52. package/src/koffi/examples/yao-pkg/README.md +17 -0
  53. package/src/koffi/examples/yao-pkg/index.js +2 -0
  54. package/src/koffi/examples/yao-pkg/package.json +22 -0
  55. package/src/koffi/src/call.cc +2 -0
  56. package/src/koffi/src/ffi.cc +40 -4
  57. package/src/koffi/src/util.cc +1 -1
  58. package/doc/Makefile +0 -20
  59. package/doc/benchmarks.xlsx +0 -0
  60. package/doc/changelog.md +0 -5
  61. package/doc/conf.py +0 -118
  62. package/doc/index.rst +0 -47
  63. package/doc/make.bat +0 -35
  64. package/doc/poetry.lock +0 -521
  65. package/doc/pyproject.toml +0 -19
  66. package/doc/static/bench_linux.png +0 -0
  67. package/doc/static/bench_windows.png +0 -0
  68. package/doc/static/custom.css +0 -70
  69. package/doc/static/node_c.webp +0 -0
  70. package/doc/static/opensans/LICENSE.txt +0 -202
  71. package/doc/static/opensans/OpenSans.css +0 -39
  72. package/doc/static/opensans/OpenSans_v17_Latin_Bold.woff +0 -0
  73. package/doc/static/opensans/OpenSans_v17_Latin_Bold.woff2 +0 -0
  74. package/doc/static/opensans/OpenSans_v17_Latin_BoldItalic.woff +0 -0
  75. package/doc/static/opensans/OpenSans_v17_Latin_BoldItalic.woff2 +0 -0
  76. package/doc/static/opensans/OpenSans_v17_Latin_Italic.woff +0 -0
  77. package/doc/static/opensans/OpenSans_v17_Latin_Italic.woff2 +0 -0
  78. package/doc/static/opensans/OpenSans_v17_Latin_Regular.woff +0 -0
  79. package/doc/static/opensans/OpenSans_v17_Latin_Regular.woff2 +0 -0
  80. package/doc/static/perf_linux_20220623.png +0 -0
  81. package/doc/static/perf_linux_20220623_2.png +0 -0
  82. package/doc/static/perf_linux_20220627.png +0 -0
  83. package/doc/static/perf_linux_20220628.png +0 -0
  84. package/doc/static/perf_linux_20220812.png +0 -0
  85. package/doc/static/perf_windows_20220623.png +0 -0
  86. package/doc/static/perf_windows_20220623_2.png +0 -0
  87. package/doc/static/perf_windows_20220627.png +0 -0
  88. package/doc/static/perf_windows_20220628.png +0 -0
  89. package/doc/static/perf_windows_20220812.png +0 -0
  90. package/doc/templates/badges.html +0 -7
  91. package/doc/templates/logo.html +0 -3
  92. /package/doc/static/{perf_linux_20231028.png → perf_linux.png} +0 -0
  93. /package/doc/static/{perf_windows_20231028.png → perf_windows.png} +0 -0
@@ -1,12 +1,10 @@
1
- # Contributing
2
-
3
- ## Bugs and feature requests
1
+ # Bugs and feature requests
4
2
 
5
3
  Use the official repository for bugs, ideas and features requests: https://github.com/Koromix/koffi
6
4
 
7
5
  Please note that the source code is not in this repository, instead it lives in a monorepo: https://github.com/Koromix/rygel/ (in the *src/koffi* subdirectory).
8
6
 
9
- ## Build from source
7
+ # Build from source
10
8
 
11
9
  We provide prebuilt binaries, packaged in the NPM archive, so in most cases it should be as simple as `npm install koffi`. If you want to hack Koffi or use a specific platform, follow the instructions below.
12
10
 
@@ -19,7 +17,7 @@ cd rygel
19
17
 
20
18
  As said before, this is a monorepository containg multiple projects, hence the name.
21
19
 
22
- ### Windows
20
+ ## Windows
23
21
 
24
22
  First, make sure the following dependencies are met:
25
23
 
@@ -34,7 +32,7 @@ cd src/koffi
34
32
  node ../cnoke/cnoke.js
35
33
  ```
36
34
 
37
- ### Other platforms
35
+ ## Other platforms
38
36
 
39
37
  Make sure the following dependencies are met:
40
38
 
@@ -50,9 +48,9 @@ cd src/koffi
50
48
  node ../cnoke/cnoke.js
51
49
  ```
52
50
 
53
- ## Run tests
51
+ # Run tests
54
52
 
55
- ### On your machine
53
+ ## On your machine
56
54
 
57
55
  Once Koffi is built, you can build the tests and run them with the following commands:
58
56
 
@@ -63,7 +61,7 @@ node ../../cnoke/cnoke.js
63
61
  node test.js
64
62
  ```
65
63
 
66
- ### On virtual machines
64
+ ## On virtual machines
67
65
 
68
66
  Koffi is tested on multiple architectures using emulated (accelerated when possible) QEMU machines. First, you need to install qemu packages, such as `qemu-system` (or even `qemu-system-gui`) on Ubuntu.
69
67
 
@@ -121,12 +119,12 @@ Each machine is configured to run a VNC server available locally, which you can
121
119
  node qemu.js info debian_x64
122
120
  ```
123
121
 
124
- ## Making a release
122
+ # Making a release
125
123
 
126
124
  First, you must update the code in three steps:
127
125
 
128
126
  - Change the version numbers in `package.json` (version and stable for stable releases)
129
- - Add an entry to `CHANGELOG.md` to summarize the changes since last release
127
+ - Add an entry to `CHANGELOG` to summarize the changes since last release
130
128
  - Commit theses changes with the message *Bump Koffi to X.Y.Z*
131
129
 
132
130
  Once this is done, you can publish a new release with the following commands:
@@ -141,7 +139,7 @@ npm publish
141
139
 
142
140
  Some platforms are emulated so this can take a few minutes until the pre-built binaries are ready. Go grab a cup of coffee, come back and execute the `npm publish` command!
143
141
 
144
- ## Code style
142
+ # Code style
145
143
 
146
144
  Koffi is programmed in a mix of C++ and assembly code (architecture-specific code). It uses [node-addon-api](https://github.com/nodejs/node-addon-api) (C++ N-API wrapper) to interact with Node.js.
147
145
 
@@ -1,6 +1,4 @@
1
- # Function calls
2
-
3
- ## Loading libraries
1
+ # Loading libraries
4
2
 
5
3
  To declare functions, start by loading the shared library with `koffi.load(filename)`.
6
4
 
@@ -15,11 +13,10 @@ This library will be automatically unloaded once all references to it are gone (
15
13
 
16
14
  Starting with *Koffi 2.3.20*, you can explicitly unload a library by calling `lib.unload()`. Any attempt to find or call a function from this library after unloading it will crash.
17
15
 
18
- ```{note}
19
- On some platforms (such as with the [musl C library on Linux](https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries)), shared libraries cannot be unloaded, so the library will remain loaded and memory mapped after the call to `lib.unload()`.
20
- ```
16
+ > [!NOTE]
17
+ > On some platforms (such as with the [musl C library on Linux](https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries)), shared libraries cannot be unloaded, so the library will remain loaded and memory mapped after the call to `lib.unload()`.
21
18
 
22
- ## Loading options
19
+ # Loading options
23
20
 
24
21
  *New in Koffi 2.6, changed in Koffi 2.8.2 and Koffi 2.8.6*
25
22
 
@@ -37,16 +34,16 @@ const lib = koffi.load('/path/to/shared/library.so', options);
37
34
 
38
35
  More options may be added if needed.
39
36
 
40
- ## Function definitions
37
+ # Function definitions
41
38
 
42
- ### Definition syntax
39
+ ## Definition syntax
43
40
 
44
41
  Use the object returned by `koffi.load()` to load C functions from the library. To do so, you can use two syntaxes:
45
42
 
46
43
  - The classic syntax, inspired by node-ffi
47
44
  - C-like prototypes
48
45
 
49
- #### Classic syntax
46
+ ### Classic syntax
50
47
 
51
48
  To declare a function, you need to specify its non-mangled name, its return type, and its parameters. Use an ellipsis as the last parameter for variadic functions.
52
49
 
@@ -57,7 +54,7 @@ const atoi = lib.func('atoi', 'int', ['str']);
57
54
 
58
55
  Koffi automatically tries mangled names for non-standard x86 calling conventions. See the section on [calling conventions](#calling-conventions) for more information on this subject.
59
56
 
60
- #### C-like prototypes
57
+ ### C-like prototypes
61
58
 
62
59
  If you prefer, you can declare functions using simple C-like prototype strings, as shown below:
63
60
 
@@ -68,7 +65,7 @@ const atoi = lib.func('int atoi(str)'); // The parameter name is not used by Kof
68
65
 
69
66
  You can use `()` or `(void)` for functions that take no argument.
70
67
 
71
- ### Variadic functions
68
+ ## Variadic functions
72
69
 
73
70
  Variadic functions are declared with an ellipsis as the last argument.
74
71
 
@@ -83,7 +80,7 @@ printf('Integer %d, double %g, str %s', 'int', 6, 'double', 8.5, 'str', 'THE END
83
80
 
84
81
  On x86 platforms, only the Cdecl convention can be used for variadic functions.
85
82
 
86
- ### Calling conventions
83
+ ## Calling conventions
87
84
 
88
85
  *Changed in Koffi 2.7*
89
86
 
@@ -100,11 +97,10 @@ Most architectures only support one procedure call standard per process. The 32-
100
97
 
101
98
  You can safely use these on non-x86 platforms, they are simply ignored.
102
99
 
103
- ```{note}
104
- Support for specifying the convention as the first argument of the classic form was introduced in Koffi 2.7.
105
-
106
- In earlier versions, you had to use `koffi.stdcall()` and similar functions. These functions are still supported but deprecated, and will be removed in Koffi 3.0.
107
- ```
100
+ > [!NOTE]
101
+ > Support for specifying the convention as the first argument of the classic form was introduced in Koffi 2.7.
102
+ >
103
+ > In earlier versions, you had to use `koffi.stdcall()` and similar functions. These functions are still supported but deprecated, and will be removed in Koffi 3.0.
108
104
 
109
105
  Below you can find a small example showing how to use a non-default calling convention, with the two syntaxes:
110
106
 
@@ -119,9 +115,9 @@ const MessageBoxA_1 = lib.func('__stdcall', 'MessageBoxA', 'int', ['void *', 'st
119
115
  const MessageBoxA_2 = lib.func('int __stdcall MessageBoxA(void *hwnd, str text, str caption, uint type)');
120
116
  ```
121
117
 
122
- ## Call types
118
+ # Call types
123
119
 
124
- ### Synchronous calls
120
+ ## Synchronous calls
125
121
 
126
122
  Once a native function has been declared, you can simply call it as you would any other JS function.
127
123
 
@@ -132,7 +128,7 @@ let value = atoi('1257');
132
128
  console.log(value);
133
129
  ```
134
130
 
135
- For [variadic functions](functions.md#variadic-functions), you msut specificy the type and the value for each additional argument.
131
+ For [variadic functions](functions#variadic-functions), you msut specificy the type and the value for each additional argument.
136
132
 
137
133
  ```js
138
134
  const printf = lib.func('printf', 'int', ['str', '...']);
@@ -141,7 +137,7 @@ const printf = lib.func('printf', 'int', ['str', '...']);
141
137
  printf('Integer %d, double %g, str %s', 'int', 6, 'double', 8.5, 'str', 'THE END');
142
138
  ```
143
139
 
144
- ### Asynchronous calls
140
+ ## Asynchronous calls
145
141
 
146
142
  You can issue asynchronous calls by calling the function through its async member. In this case, you need to provide a callback function as the last argument, with `(err, res)` parameters.
147
143
 
@@ -169,13 +165,12 @@ You can easily convert this callback-style async function to a promise-based ver
169
165
 
170
166
  Variadic functions cannot be called asynchronously.
171
167
 
172
- ```{warning}
173
- Asynchronous functions run on worker threads. You need to deal with thread safety issues if you share data between threads.
174
-
175
- Callbacks must be called from the main thread, or more precisely from the same thread as the V8 intepreter. Calling a callback from another thread is undefined behavior, and will likely lead to a crash or a big mess. You've been warned!
176
- ```
168
+ > [!WARNING]
169
+ > Asynchronous functions run on worker threads. You need to deal with thread safety issues if you share data between threads.
170
+ >
171
+ > Callbacks must be called from the main thread, or more precisely from the same thread as the V8 intepreter. Calling a callback from another thread is undefined behavior, and will likely lead to a crash or a big mess. You've been warned!
177
172
 
178
- ## Function pointers
173
+ # Function pointers
179
174
 
180
175
  *New in Koffi 2.4*
181
176
 
@@ -204,7 +199,7 @@ BinaryIntFunc *GetBinaryIntFunction(const char *type)
204
199
  }
205
200
  ```
206
201
 
207
- ### Call pointer directly
202
+ ## Call pointer directly
208
203
 
209
204
  Use `koffi.call(ptr, type, ...)` to call a function pointer. The first two arguments are the pointer itself and the type of the function you are trying to call (declared with `koffi.proto()` as shown below), and the remaining arguments are used for the call.
210
205
 
@@ -223,7 +218,7 @@ let delta = koffi.call(substract_ptr, BinaryIntFunc, 100, 58);
223
218
  console.log(sum, delta); // Prints 9 and 42
224
219
  ```
225
220
 
226
- ### Decode pointer to function
221
+ ## Decode pointer to function
227
222
 
228
223
  Use `koffi.decode(ptr, type)` to get back a JS function, which you can then use like any other Koffi function.
229
224
 
@@ -244,12 +239,12 @@ let delta = substract(100, 58);
244
239
  console.log(sum, delta); // Prints 9 and 42
245
240
  ```
246
241
 
247
- ## Conversion of parameters
242
+ # Conversion of parameters
248
243
 
249
244
  By default, Koffi will only forward and translate arguments from Javascript to C. However, many C functions use pointer arguments for output values, or input/output values.
250
245
 
251
246
  Among other thing, in the the following pages you will learn more about:
252
247
 
253
- - How Koffi translates [input parameters](input.md) to C
254
- - How you can [define and use pointers](pointers.md)
255
- - How to deal with [output parameters](output.md)
248
+ - How Koffi translates [input parameters](input) to C
249
+ - How you can [define and use pointers](pointers)
250
+ - How to deal with [output parameters](output)
@@ -0,0 +1,20 @@
1
+ # Koffi
2
+
3
+ Koffi is a **fast and easy-to-use C FFI module for Node.js**, featuring:
4
+
5
+ * Low-overhead and fast performance (see [benchmarks](benchmarks))
6
+ * Support for primitive and aggregate data types (structs and fixed-size arrays), both by reference (pointer) and by value
7
+ * Javascript functions can be used as C callbacks (since 1.2.0)
8
+ * Well-tested code base for [popular OS/architecture combinations](platforms)
9
+
10
+ Koffi requires a recent [Node.js](https://nodejs.org/) version with N-API version 8 support, see [this page](platforms) for more information.
11
+
12
+ The source code is available here: https://github.com/Koromix/rygel/ (in the *src/koffi* subdirectory).
13
+
14
+ New releases are frequent, look at the [changelog](changelog) for more information.
15
+
16
+ # License
17
+
18
+ This program is free software: you can redistribute it and/or modify it under the terms of the **MIT License**.
19
+
20
+ Find more information here: https://choosealicense.com/licenses/mit/
@@ -1,8 +1,6 @@
1
- # Input parameters
1
+ # Primitive types
2
2
 
3
- ## Primitive types
4
-
5
- ### Standard types
3
+ ## Standard types
6
4
 
7
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:
8
6
 
@@ -59,7 +57,7 @@ let struct1 = koffi.struct({ dummy: 'long' });
59
57
  let struct2 = koffi.struct({ dummy: koffi.types.long });
60
58
  ```
61
59
 
62
- ### Endian-sensitive integers
60
+ ## Endian-sensitive integers
63
61
 
64
62
  *New in Koffi 2.1*
65
63
 
@@ -80,9 +78,9 @@ int64_be, int64_be_t | 8 | Signed | Big Endian
80
78
  uint64_le, uint64_le_t | 8 | Unsigned | Little Endian
81
79
  uint64_be, uint64_be_t | 8 | Unsigned | Big Endian
82
80
 
83
- ## Struct types
81
+ # Struct types
84
82
 
85
- ### Struct definition
83
+ ## Struct definition
86
84
 
87
85
  Koffi converts JS objects to C structs, and vice-versa.
88
86
 
@@ -141,23 +139,22 @@ const Function1 = lib.func('A Function(A value)');
141
139
  const Function2 = lib.func('Function', A, [A]);
142
140
  ```
143
141
 
144
- ### Opaque types
142
+ ## Opaque types
145
143
 
146
144
  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 opaque pointer with other functions such as `fread()` or `ftell()`.
147
145
 
148
- In Koffi, you can manage this with opaque types. Declare the opaque type with `koffi.opaque(name)`, and use a pointer to this type either as a return type or some kind of [output parameter](output.md) (with a double pointer).
149
-
150
- ```{note}
151
- Opaque types **have changed in version 2.0, and again in version 2.1**.
152
-
153
- 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.
154
-
155
- 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](output.md).
146
+ In Koffi, you can manage this with opaque types. Declare the opaque type with `koffi.opaque(name)`, and use a pointer to this type either as a return type or some kind of [output parameter](output) (with a double pointer).
156
147
 
157
- In addition to this, you should use `koffi.opaque()` (introduced in Koffi 2.1) instead of `koffi.handle()` which is deprecated, and will be removed eventually in Koffi 3.0.
158
-
159
- Consult the [migration guide](migration.md) for more information.
160
- ```
148
+ > [!NOTE]
149
+ > Opaque types **have changed in version 2.0, and again in version 2.1**.
150
+ >
151
+ > 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.
152
+ >
153
+ > 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](output).
154
+ >
155
+ > In addition to this, you should use `koffi.opaque()` (introduced in Koffi 2.1) instead of `koffi.handle()` which is deprecated, and will be removed eventually in Koffi 3.0.
156
+ >
157
+ > Consult the [migration guide](migration) for more information.
161
158
 
162
159
  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: `ConcatNew` (or `ConcatNewOut`) and `ConcatFree`.
163
160
 
@@ -335,9 +332,9 @@ try {
335
332
  }
336
333
  ```
337
334
 
338
- ## Array types
335
+ # Array types
339
336
 
340
- ### Fixed-size C arrays
337
+ ## Fixed-size C arrays
341
338
 
342
339
  *Changed in Koffi 2.7.1*
343
340
 
@@ -381,11 +378,10 @@ const StructType = koffi.struct('StructType', {
381
378
  });
382
379
  ```
383
380
 
384
- ```{note}
385
- The short C-like syntax was introduced in Koffi 2.7.1, use `koffi.array()` for older versions.
386
- ```
381
+ > [!NOTE]
382
+ > The short C-like syntax was introduced in Koffi 2.7.1, use `koffi.array()` for older versions.
387
383
 
388
- ### Fixed-size string buffers
384
+ ## Fixed-size string buffers
389
385
 
390
386
  *Changed in Koffi 2.9.0*
391
387
 
@@ -395,16 +391,15 @@ Koffi can also convert JS strings to fixed-sized arrays in the following cases:
395
391
  - **char16 (or char16_t) arrays** are filled with the UTF-16 encoded string, truncated if needed. The buffer is always NUL-terminated.
396
392
  - **char32 (or char32_t) arrays** are filled with the UTF-32 encoded string, truncated if needed. The buffer is always NUL-terminated.
397
393
 
398
- ```{note}
399
- Support for UTF-32 and wchar_t (wide) strings was introduced in Koffi 2.9.0.
400
- ```
394
+ > [!NOTE]
395
+ > Support for UTF-32 and wchar_t (wide) strings was introduced in Koffi 2.9.0.
401
396
 
402
397
  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_t and char32_t arrays, but you can also explicitly ask for this with the `String` array hint (e.g. `koffi.array('char', 8, 'String')`).
403
398
 
404
- ### Dynamic arrays (pointers)
399
+ ## Dynamic arrays (pointers)
405
400
 
406
- In C, dynamically-sized arrays are usually passed around as pointers. Read more about [array pointers](pointers.md#dynamic-arrays) in the relevant section.
401
+ In C, dynamically-sized arrays are usually passed around as pointers. Read more about [array pointers](pointers#dynamic-arrays) in the relevant section.
407
402
 
408
- ## Union types
403
+ # Union types
409
404
 
410
- The declaration and use of [unions types](unions.md) will be explained in a later section, they are only briefly mentioned here if you need them.
405
+ The declaration and use of [union types](unions) will be explained in a later section, they are only briefly mentioned here if you need them.
@@ -1,6 +1,4 @@
1
- # Migration guide
2
-
3
- ## Koffi 1.x to 2.x
1
+ # Koffi 1.x to 2.x
4
2
 
5
3
  The API was changed in 2.x in a few ways, in order to reduce some excessively "magic" behavior and reduce the syntax differences between C and the C-like prototypes.
6
4
 
@@ -10,7 +8,7 @@ You may need to change your code if you use:
10
8
  - Opaque types
11
9
  - `koffi.introspect()`
12
10
 
13
- ### Callback type changes
11
+ ## Callback type changes
14
12
 
15
13
  In Koffi 1.x, callbacks were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer. Now, you must use them through a pointer: `void CallIt(CallbackType func)` in Koffi 1.x becomes `void CallIt(CallbackType *func)` in version 2.0 and newer.
16
14
 
@@ -61,13 +59,12 @@ let ret = TransferToJS('Niels', 27, (str, age) => {
61
59
  console.log(ret);
62
60
  ```
63
61
 
64
- Koffi 1.x only supported [transient callbacks](callbacks.md#javascript-callbacks), you must use Koffi 2.x for registered callbacks.
62
+ Koffi 1.x only supported [transient callbacks](callbacks#javascript-callbacks), you must use Koffi 2.x for registered callbacks.
65
63
 
66
- ```{note}
67
- The function `koffi.proto()` was introduced in Koffi 2.4, it was called `koffi.callback()` in earlier versions.
68
- ```
64
+ > [!NOTE]
65
+ > The function `koffi.proto()` was introduced in Koffi 2.4, it was called `koffi.callback()` in earlier versions.
69
66
 
70
- ### Opaque type changes
67
+ ## Opaque type changes
71
68
 
72
69
  In Koffi 1.x, opaque handles were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer. Now, in Koffi 2.0, you must use them through a pointer, and use an array for output parameters.
73
70
 
@@ -145,7 +142,7 @@ db = ptr[0];
145
142
  sqlite3_close_v2(db);
146
143
  ```
147
144
 
148
- ### New koffi.introspect()
145
+ ## New koffi.introspect()
149
146
 
150
147
  In Koffi 1.x, `koffi.introspect()` would only work with struct types, and return the object passed to `koffi.struct()` to initialize the type. Now this function works with all types.
151
148
 
@@ -1,20 +1,17 @@
1
- # Miscellaneous
1
+ # Types
2
2
 
3
- ## Types
4
-
5
- ### Introspection
3
+ ## Introspection
6
4
 
7
5
  *New in Koffi 2.0: `koffi.resolve()`, new in Koffi 2.2: `koffi.offsetof()`*
8
6
 
9
- ```{note}
10
- The value returned by `introspect()` has **changed in version 2.0 and in version 2.2**.
11
-
12
- 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.
13
-
14
- Starting in Koffi 2.2, each record member is exposed as an object containing the name, the type and the offset within the record.
15
-
16
- Consult the [migration guide](migration.md) for more information.
17
- ```
7
+ > [!NOTE]
8
+ > The value returned by `introspect()` has **changed in version 2.0 and in version 2.2**.
9
+ >
10
+ > 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.
11
+ >
12
+ > Starting in Koffi 2.2, each record member is exposed as an object containing the name, the type and the offset within the record.
13
+ >
14
+ > Consult the [migration guide](migration) for more information.
18
15
 
19
16
  Use `koffi.introspect(type)` to get detailed information about a type: name, primitive, size, alignment, members (record types), reference type (array, pointer) and length (array).
20
17
 
@@ -56,15 +53,50 @@ console.log(koffi.sizeof('long'));
56
53
  console.log(koffi.sizeof(koffi.types.long));
57
54
  ```
58
55
 
59
- ### Aliases
56
+ ## Aliases
60
57
 
61
58
  *New in Koffi 2.0*
62
59
 
63
60
  You can alias a type with `koffi.alias(name, type)`. Aliased types are completely equivalent.
64
61
 
65
- ## Settings
62
+ ## Circular references
63
+
64
+ *New in Koffi 2.10.0*
65
+
66
+ In some cases, composite types can point to each other and thus depend on each other. This can also happen when a function takes a pointer to a struct that also contains a function pointer.
67
+
68
+ To deal with this, you can create an opaque type and redefine it later to a concrete struct or union type, as shown below.
69
+
70
+ ```js
71
+ const Type1 = koffi.opaque('Type1');
72
+
73
+ const Type2 = koffi.struct('Type2', {
74
+ ptr: 'Type1 *',
75
+ i: 'int'
76
+ });
66
77
 
67
- ### Memory usage
78
+ // Redefine Type1 to a concrete type
79
+ koffi.struct(Type1, {
80
+ ptr: 'Type2 *',
81
+ f: 'float'
82
+ });
83
+ ```
84
+
85
+ > [!NOTE]
86
+ > You must use a proper type object when you redefine the type. If you only have the name, use `koffi.resolve()` to get a type object from a type string.
87
+ >
88
+ > ```js
89
+ > const MyType = koffi.opaque('MyType');
90
+ >
91
+ > // This does not work, you must use the MyType object and not a type string
92
+ > koffi.struct('MyType', {
93
+ > ptr: 'Type2 *',
94
+ > f: 'float'
95
+ > });
96
+
97
+ # Settings
98
+
99
+ ## Memory usage
68
100
 
69
101
  For synchronous/normal calls, Koffi uses two preallocated memory blocks:
70
102
 
@@ -84,7 +116,7 @@ The same is true for asynchronous calls. When an asynchronous call is made, Koff
84
116
 
85
117
  There cannot be more than `max_async_calls` running at the same time.
86
118
 
87
- ### Default settings
119
+ ## Default settings
88
120
 
89
121
  Setting | Default | Description
90
122
  -------------------- | ------- | -----------------------------------------------
@@ -96,13 +128,13 @@ resident_async_pools | 2 | Number of resident pools for asynchronous calls
96
128
  max_async_calls | 64 | Maximum number of ongoing asynchronous calls
97
129
  max_type_size | 64 MiB | Maximum size of Koffi types (for arrays and structs)
98
130
 
99
- ## Usage statistics
131
+ # Usage statistics
100
132
 
101
133
  *New in Koffi 2.3.2*
102
134
 
103
135
  You can use `koffi.stats()` to get a few statistics related to Koffi.
104
136
 
105
- ## POSIX error codes
137
+ # POSIX error codes
106
138
 
107
139
  *New in Koffi 2.3.14*
108
140
 
@@ -126,7 +158,7 @@ assert.equal(koffi.errno(), koffi.os.errno.EBADF);
126
158
  console.log('close() with invalid FD is POSIX compliant!');
127
159
  ```
128
160
 
129
- ## Reset internal state
161
+ # Reset internal state
130
162
 
131
163
  *New in Koffi 2.5.19*
132
164
 
@@ -137,6 +169,5 @@ You can use `koffi.reset()` to clear some Koffi internal state such as:
137
169
 
138
170
  This function is mainly intended for test code, when you execute the same code over and over and you need to reuse type names.
139
171
 
140
- ```{warning}
141
- Trying to use a function or a type that was initially defined before the reset is undefined behavior and will likely lead to a crash!
142
- ```
172
+ > [!WARNING]
173
+ > Trying to use a function or a type that was initially defined before the reset is undefined behavior and will likely lead to a crash!
@@ -1,12 +1,10 @@
1
- # Output parameters
2
-
3
- ## Output and input/output
1
+ # Output and input/output
4
2
 
5
3
  For simplicity, and because Javascript only has value semantics for primitive types, Koffi can marshal out (or in/out) multiple types of parameters:
6
4
 
7
- - [Structs](input.md#struct-types) (to/from JS objects)
8
- - [Unions](unions.md)
9
- - [Opaque types](input.md#opaque-types)
5
+ - [Structs](input#struct-types) (to/from JS objects)
6
+ - [Unions](unions)
7
+ - [Opaque types](input#opaque-types)
10
8
  - String buffers
11
9
 
12
10
  In order to change an argument from input-only to output or input/output, use the following functions:
@@ -19,7 +17,7 @@ The same can be done when declaring a function with a C-like prototype string, w
19
17
  - `_Out_` for output parameters
20
18
  - `_Inout_` for dual input/output parameters
21
19
 
22
- ### Primitive value
20
+ ## Primitive value
23
21
 
24
22
  This Windows example enumerate all Chrome windows along with their PID and their title. The `GetWindowThreadProcessId()` function illustrates how to get a primitive value from an output argument.
25
23
 
@@ -75,7 +73,7 @@ for (let hwnd = null;;) {
75
73
  }
76
74
  ```
77
75
 
78
- ### Struct example
76
+ ## Struct example
79
77
 
80
78
  This example calls the POSIX function `gettimeofday()`, and uses the prototype-like syntax.
81
79
 
@@ -103,7 +101,7 @@ gettimeofday(tv, null);
103
101
  console.log(tv);
104
102
  ```
105
103
 
106
- ### Opaque type example
104
+ ## Opaque type example
107
105
 
108
106
  This example opens an in-memory SQLite database, and uses the node-ffi-style function declaration syntax.
109
107
 
@@ -130,7 +128,7 @@ let db = out[0];
130
128
  sqlite3_close_v2(db);
131
129
  ```
132
130
 
133
- ### String buffer example
131
+ ## String buffer example
134
132
 
135
133
  *New in Koffi 2.2*
136
134
 
@@ -168,17 +166,16 @@ ConcatToBuffer(str1, str2, out);
168
166
  console.log(out[0]);
169
167
  ```
170
168
 
171
- ## Output buffers
169
+ # Output buffers
172
170
 
173
171
  In most cases, you can use buffers and typed arrays to provide output buffers. This works as long as the buffer only gets used while the native C function is being called. See [transient pointers](#transient-pointers) below for an example.
174
172
 
175
- ```{warning}
176
- It is unsafe to keep the pointer around in the native code, or to change the contents outside of the function call where it is provided.
177
-
178
- If you need to provide a pointer that will be kept around, allocate memory with [koffi.alloc()](#stable-pointers) instead.
179
- ```
173
+ > [!WARNING]
174
+ > It is unsafe to keep the pointer around in the native code, or to change the contents outside of the function call where it is provided.
175
+ >
176
+ > If you need to provide a pointer that will be kept around, allocate memory with [koffi.alloc()](#stable-pointers) instead.
180
177
 
181
- ### Transient pointers
178
+ ## Transient pointers
182
179
 
183
180
  *New in Koffi 2.3*
184
181
 
@@ -220,9 +217,9 @@ console.log(vec1); // { x: 3, y: 2, z: 1 }
220
217
  console.log(vec2); // { x: 1, y: 2, z: 3 }
221
218
  ```
222
219
 
223
- See [decoding variables](variables.md#decode-to-js-values) for more information about the decode function.
220
+ See [decoding variables](variables#decode-to-js-values) for more information about the decode function.
224
221
 
225
- ### Stable pointers
222
+ ## Stable pointers
226
223
 
227
224
  *New in Koffi 2.8*
228
225
 
@@ -230,7 +227,7 @@ In some cases, the native code may need to change the output buffer at a later t
230
227
 
231
228
  In this case, it is **not safe to use buffers or typed arrays**!
232
229
 
233
- However, you can use `koffi.alloc(type, len)` to allocate memory and get a pointer that won't move, and can be safely used at any time by the native code. Use [koffi.decode()](variables.md#decode-to-js-values) to read data from the pointer when needed.
230
+ However, you can use `koffi.alloc(type, len)` to allocate memory and get a pointer that won't move, and can be safely used at any time by the native code. Use [koffi.decode()](variables#decode-to-js-values) to read data from the pointer when needed.
234
231
 
235
232
  The example below sets up some memory to be used as an output buffer where a concatenation function appends a string on each call.
236
233