koffi 2.0.1 → 2.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +1 -8
- package/benchmark/atoi_koffi.js +12 -8
- package/benchmark/atoi_napi.js +12 -8
- package/benchmark/atoi_node_ffi.js +11 -10
- package/benchmark/raylib_cc.cc +12 -9
- package/benchmark/raylib_koffi.js +15 -13
- package/benchmark/raylib_node_ffi.js +15 -13
- package/benchmark/raylib_node_raylib.js +14 -11
- package/build/qemu/2.1.0-beta.1/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_win32_x64.tar.gz +0 -0
- package/doc/changes.md +12 -8
- package/doc/dist/doctrees/changes.doctree +0 -0
- package/doc/dist/doctrees/environment.pickle +0 -0
- package/doc/dist/doctrees/functions.doctree +0 -0
- package/doc/dist/doctrees/index.doctree +0 -0
- package/doc/dist/doctrees/types.doctree +0 -0
- package/doc/dist/html/_sources/changes.md.txt +12 -8
- package/doc/dist/html/_sources/functions.md.txt +4 -4
- package/doc/dist/html/_sources/types.md.txt +69 -34
- package/doc/dist/html/benchmarks.html +1 -1
- package/doc/dist/html/changes.html +44 -33
- package/doc/dist/html/contribute.html +1 -1
- package/doc/dist/html/functions.html +7 -7
- package/doc/dist/html/genindex.html +1 -1
- package/doc/dist/html/index.html +3 -3
- package/doc/dist/html/memory.html +1 -1
- package/doc/dist/html/objects.inv +0 -0
- package/doc/dist/html/platforms.html +2 -2
- package/doc/dist/html/search.html +1 -1
- package/doc/dist/html/searchindex.js +1 -1
- package/doc/dist/html/start.html +1 -1
- package/doc/dist/html/types.html +77 -40
- package/doc/functions.md +4 -4
- package/doc/types.md +68 -33
- package/package.json +2 -2
- package/qemu/qemu.js +1 -1
- package/src/call.cc +42 -26
- package/src/call.hh +15 -3
- package/src/ffi.cc +70 -13
- package/src/ffi.hh +7 -0
- package/src/index.js +4 -2
- package/src/parser.cc +3 -5
- package/src/util.cc +44 -1
- package/src/util.hh +4 -0
- package/test/async.js +1 -2
- package/test/callbacks.js +2 -3
- package/test/misc.c +21 -1
- package/test/raylib.js +1 -1
- package/test/sqlite.js +3 -3
- package/test/sync.js +27 -3
- package/build/qemu/2.0.1/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.0.1/koffi_win32_x64.tar.gz +0 -0
|
@@ -6,7 +6,7 @@ While the C standard allows for variation in the size of most integer types, Kof
|
|
|
6
6
|
|
|
7
7
|
JS type | C type | Bytes | Signedness | Note
|
|
8
8
|
----------------- | ------------------ | ----- | ---------- | ---------------------------
|
|
9
|
-
|
|
9
|
+
Undefined | void | 0 | | Only valid as a return type
|
|
10
10
|
Number (integer) | int8 | 1 | Signed |
|
|
11
11
|
Number (integer) | int8_t | 1 | Signed |
|
|
12
12
|
Number (integer) | uint8 | 1 | Unsigned |
|
|
@@ -69,6 +69,8 @@ let struct2 = koffi.struct({ dummy: koffi.types.long });
|
|
|
69
69
|
|
|
70
70
|
## Struct types
|
|
71
71
|
|
|
72
|
+
### Struct definition
|
|
73
|
+
|
|
72
74
|
Koffi converts JS objects to C structs, and vice-versa.
|
|
73
75
|
|
|
74
76
|
Unlike function declarations, as of now there is only one way to create a struct type, with the `koffi.struct()` function. This function takes two arguments: the first one is the name of the type, and the second one is an object containing the struct member names and types. You can omit the first argument to declare an anonymous struct.
|
|
@@ -109,56 +111,44 @@ const Function1 = lib.func('A Function(A value)');
|
|
|
109
111
|
const Function2 = lib.func('Function', A, [A]);
|
|
110
112
|
```
|
|
111
113
|
|
|
112
|
-
|
|
114
|
+
Koffi automatically follows the platform C ABI regarding alignment and padding. However, you can override these rules if needed with:
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
- **Struct pointers**: Use of struct pointers by C libraries fall in two cases: avoid (potentially) expensive copies, and to let the function change struct contents (output or input/output arguments).
|
|
117
|
-
- **Opaque handles**: the library does not expose the contents of the structs, and only provides you with a pointer to it (e.g. `FILE *`). Only the functions provided by the library can do something with this pointer, in Koffi we call this a handle. This is usually done for ABI-stability reason, and to prevent library users from messing directly with library internals.
|
|
118
|
-
- **Arrays**: in C, you dynamically-sized arrays are usually passed to functions with pointers, either NULL-terminated (or any other sentinel value) or with an additional length argument.
|
|
119
|
-
- **Pointers to primitive types**: This is more rare, and generally used for output or input/output arguments. The Win32 API has a lot of these.
|
|
120
|
-
|
|
121
|
-
### Struct pointers
|
|
122
|
-
|
|
123
|
-
The following Win32 example uses `GetCursorPos()` (with an output parameter) to retrieve and show the current cursor position.
|
|
116
|
+
- Pack all members without padding with `koffi.pack()` (instead of `koffi.struct()`)
|
|
117
|
+
- Change alignment of a specific member as shown below
|
|
124
118
|
|
|
125
119
|
```js
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const POINT = koffi.struct('POINT', {
|
|
131
|
-
x: 'long',
|
|
132
|
-
y: 'long'
|
|
120
|
+
// This struct is 3 bytes long
|
|
121
|
+
const PackedStruct = koffi.pack('PackedStruct', {
|
|
122
|
+
a: 'int8_t',
|
|
123
|
+
b: 'int16_t'
|
|
133
124
|
});
|
|
134
125
|
|
|
135
|
-
//
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (!GetCursorPos(pos))
|
|
141
|
-
throw new Error('Failed to get cursor position');
|
|
142
|
-
console.log(pos);
|
|
126
|
+
// This one is 18 bytes long, the second member has an alignment requirement of 16 bytes
|
|
127
|
+
const BigStruct = koffi.struct('BigStruct', {
|
|
128
|
+
a: 'int8_t',
|
|
129
|
+
b: [16, 'int16_t']
|
|
130
|
+
})
|
|
143
131
|
```
|
|
144
132
|
|
|
145
|
-
### Opaque
|
|
133
|
+
### Opaque types
|
|
146
134
|
|
|
147
|
-
Many C libraries use some kind of object-oriented API, with a pair of functions dedicated to create and delete objects. An obvious example of this can be found in stdio.h, with the opaque `FILE *` pointer. You can open and close files with `fopen()` and `fclose()`, and manipule the
|
|
135
|
+
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()`.
|
|
148
136
|
|
|
149
|
-
In Koffi, you can manage this with opaque
|
|
137
|
+
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](functions.md#output-parameters) (with a double pointer).
|
|
150
138
|
|
|
151
139
|
```{note}
|
|
152
|
-
Opaque
|
|
140
|
+
Opaque types **have changed in version 2.0, and again in version 2.1**.
|
|
153
141
|
|
|
154
142
|
In Koffi 1.x, opaque handles were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer.
|
|
155
143
|
|
|
156
144
|
Now, you must use them through a pointer, and use an array for output parameters. This is shown in the example below (look for the call to `ConcatNewOut` in the JS part), and is described in the section on [output parameters](functions.md#output-parameters).
|
|
157
145
|
|
|
146
|
+
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.
|
|
147
|
+
|
|
158
148
|
Consult the [migration guide](changes.md) for more information.
|
|
159
149
|
```
|
|
160
150
|
|
|
161
|
-
The full example below implements an iterative string builder (concatenator) in C, and uses it from Javascript to output a mix of Hello World and FizzBuzz. The builder is hidden behind an opaque
|
|
151
|
+
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`.
|
|
162
152
|
|
|
163
153
|
```c
|
|
164
154
|
// Build with: clang -fPIC -o handles.so -shared handles.c -Wall -O2
|
|
@@ -283,7 +273,7 @@ const char *ConcatBuild(Concat *c)
|
|
|
283
273
|
const koffi = require('koffi');
|
|
284
274
|
const lib = koffi.load('./handles.so');
|
|
285
275
|
|
|
286
|
-
const Concat = koffi.
|
|
276
|
+
const Concat = koffi.opaque('Concat');
|
|
287
277
|
const ConcatNewOut = lib.func('bool ConcatNewOut(_Out_ Concat **out)');
|
|
288
278
|
const ConcatNew = lib.func('Concat *ConcatNew()');
|
|
289
279
|
const ConcatFree = lib.func('void ConcatFree(Concat *c)');
|
|
@@ -332,6 +322,51 @@ try {
|
|
|
332
322
|
}
|
|
333
323
|
```
|
|
334
324
|
|
|
325
|
+
## Pointer types
|
|
326
|
+
|
|
327
|
+
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:
|
|
328
|
+
|
|
329
|
+
- **Struct pointers**: Use of struct pointers by C libraries fall in two cases: avoid (potentially) expensive copies, and to let the function change struct contents (output or input/output arguments).
|
|
330
|
+
- **Opaque pointers**: the library does not expose the contents of the structs, and only provides you with a pointer to it (e.g. `FILE *`). Only the functions provided by the library can do something with this pointer, in Koffi we call this an opaque type. This is usually done for ABI-stability reason, and to prevent library users from messing directly with library internals.
|
|
331
|
+
- **Arrays**: in C, you dynamically-sized arrays are usually passed to functions with pointers, either NULL-terminated (or any other sentinel value) or with an additional length argument.
|
|
332
|
+
- **Pointers to primitive types**: This is more rare, and generally used for output or input/output arguments. The Win32 API has a lot of these.
|
|
333
|
+
|
|
334
|
+
### Struct pointers
|
|
335
|
+
|
|
336
|
+
The following Win32 example uses `GetCursorPos()` (with an output parameter) to retrieve and show the current cursor position.
|
|
337
|
+
|
|
338
|
+
```js
|
|
339
|
+
const koffi = require('koffi');
|
|
340
|
+
const lib = koffi.load('kernel32.dll');
|
|
341
|
+
|
|
342
|
+
// Type declarations
|
|
343
|
+
const POINT = koffi.struct('POINT', {
|
|
344
|
+
x: 'long',
|
|
345
|
+
y: 'long'
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Functions declarations
|
|
349
|
+
const GetCursorPos = lib.func('int __stdcall GetCursorPos(_Out_ POINT *pos)');
|
|
350
|
+
|
|
351
|
+
// Get and show cursor position
|
|
352
|
+
let pos = {};
|
|
353
|
+
if (!GetCursorPos(pos))
|
|
354
|
+
throw new Error('Failed to get cursor position');
|
|
355
|
+
console.log(pos);
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Named pointer types
|
|
359
|
+
|
|
360
|
+
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 **named pointer type** to an opaque type, like so:
|
|
361
|
+
|
|
362
|
+
```js
|
|
363
|
+
const HANDLE = koffi.pointer('HANDLE', koffi.opaque());
|
|
364
|
+
|
|
365
|
+
// And now you get to use it this way:
|
|
366
|
+
const GetHandleInformation = lib.func('bool __stdcall GetHandleInformation(HANDLE h, _Out_ uint32_t *flags)');
|
|
367
|
+
const CloseHandle = lib.func('bool __stdcall CloseHandle(HANDLE h)');
|
|
368
|
+
```
|
|
369
|
+
|
|
335
370
|
### Array pointers
|
|
336
371
|
|
|
337
372
|
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).
|
|
@@ -380,7 +415,7 @@ Here is an example based on the Win32 API, listing files in the current director
|
|
|
380
415
|
const koffi = require('koffi');
|
|
381
416
|
const lib = koffi.load('kernel32.dll');
|
|
382
417
|
|
|
383
|
-
const HANDLE = koffi.pointer('HANDLE', koffi.
|
|
418
|
+
const HANDLE = koffi.pointer('HANDLE', koffi.opaque());
|
|
384
419
|
const FILETIME = koffi.struct('FILETIME', {
|
|
385
420
|
dwLowDateTime: 'uint',
|
|
386
421
|
dwHighDateTime: 'uint'
|
|
@@ -174,8 +174,8 @@
|
|
|
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.0.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
179
|
</div>
|
|
180
180
|
</div>
|
|
181
181
|
|
|
@@ -174,8 +174,8 @@
|
|
|
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.0.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
179
|
</div>
|
|
180
180
|
</div>
|
|
181
181
|
|
|
@@ -211,6 +211,13 @@
|
|
|
211
211
|
<h1>Changelog<a class="headerlink" href="#changelog" title="Permalink to this heading">#</a></h1>
|
|
212
212
|
<section id="history">
|
|
213
213
|
<h2>History<a class="headerlink" href="#history" title="Permalink to this heading">#</a></h2>
|
|
214
|
+
<section id="koffi-2-0-1">
|
|
215
|
+
<h3>Koffi 2.0.1<a class="headerlink" href="#koffi-2-0-1" title="Permalink to this heading">#</a></h3>
|
|
216
|
+
<p><strong>Main changes:</strong></p>
|
|
217
|
+
<ul class="simple">
|
|
218
|
+
<li><p>Return <code class="docutils literal notranslate"><span class="pre">undefined</span></code> (instead of null) for <code class="docutils literal notranslate"><span class="pre">void</span></code> functions</p></li>
|
|
219
|
+
</ul>
|
|
220
|
+
</section>
|
|
214
221
|
<section id="koffi-2-0-0">
|
|
215
222
|
<h3>Koffi 2.0.0<a class="headerlink" href="#koffi-2-0-0" title="Permalink to this heading">#</a></h3>
|
|
216
223
|
<p><strong>Major new features:</strong></p>
|
|
@@ -421,7 +428,7 @@
|
|
|
421
428
|
<p>You may need to change your code if you use:</p>
|
|
422
429
|
<ul class="simple">
|
|
423
430
|
<li><p>Callback functions</p></li>
|
|
424
|
-
<li><p>Opaque
|
|
431
|
+
<li><p>Opaque types</p></li>
|
|
425
432
|
<li><p><code class="docutils literal notranslate"><span class="pre">koffi.introspect()</span></code></p></li>
|
|
426
433
|
</ul>
|
|
427
434
|
<section id="callback-types">
|
|
@@ -471,10 +478,11 @@
|
|
|
471
478
|
</div>
|
|
472
479
|
<p>Koffi 1.x only supported <a class="reference internal" href="functions#javascript-callbacks"><span class="std std-doc">transient callbacks</span></a>, you must use Koffi 2.x for registered callbacks.</p>
|
|
473
480
|
</section>
|
|
474
|
-
<section id="opaque-
|
|
475
|
-
<h4>Opaque
|
|
476
|
-
<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. Now, you must use them through a pointer, and use an array for output parameters.</p>
|
|
477
|
-
<p>
|
|
481
|
+
<section id="opaque-types">
|
|
482
|
+
<h4>Opaque types<a class="headerlink" href="#opaque-types" title="Permalink to this heading">#</a></h4>
|
|
483
|
+
<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. Now, in Koffi 2.0, you must use them through a pointer, and use an array for output parameters.</p>
|
|
484
|
+
<p>In addition to that, <code class="docutils literal notranslate"><span class="pre">koffi.handle()</span></code> has been deprecated in Koffi 2.1 and replaced with <code class="docutils literal notranslate"><span class="pre">koffi.opaque()</span></code>. They work the same but new code should use <code class="docutils literal notranslate"><span class="pre">koffi.opaque()</span></code>, the former one will eventually be removed in Koffi 3.0.</p>
|
|
485
|
+
<p>For functions that return opaque pointers or pass them by parameter:</p>
|
|
478
486
|
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
|
|
479
487
|
<span class="linenos"> 2</span>
|
|
480
488
|
<span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">FILE</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">'FILE'</span><span class="p">);</span>
|
|
@@ -487,16 +495,17 @@
|
|
|
487
495
|
<span class="linenos">10</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
|
|
488
496
|
</pre></div>
|
|
489
497
|
</div>
|
|
490
|
-
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.
|
|
498
|
+
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.1</span>
|
|
491
499
|
<span class="linenos"> 2</span>
|
|
492
|
-
<span class="linenos"> 3</span><span class="
|
|
493
|
-
<span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">
|
|
494
|
-
<span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">fopen</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">'
|
|
495
|
-
<span class="linenos"> 6</span>
|
|
496
|
-
<span class="linenos"> 7</span
|
|
497
|
-
<span class="linenos"> 8</span><span class="
|
|
498
|
-
<span class="linenos"> 9</span
|
|
499
|
-
<span class="linenos">10</span
|
|
500
|
+
<span class="linenos"> 3</span><span class="c1">// If you use Koffi 2.0: const FILE = koffi.handle('FILE');</span>
|
|
501
|
+
<span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">FILE</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">'FILE'</span><span class="p">);</span>
|
|
502
|
+
<span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">fopen</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">'fopen'</span><span class="p">,</span> <span class="s1">'FILE *'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'str'</span><span class="p">,</span> <span class="s1">'str'</span><span class="p">]);</span>
|
|
503
|
+
<span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">fopen</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">'fclose'</span><span class="p">,</span> <span class="s1">'int'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'FILE *'</span><span class="p">]);</span>
|
|
504
|
+
<span class="linenos"> 7</span>
|
|
505
|
+
<span class="linenos"> 8</span><span class="kd">let</span> <span class="nx">fp</span> <span class="o">=</span> <span class="nx">fopen</span><span class="p">(</span><span class="s1">'EMPTY'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">);</span>
|
|
506
|
+
<span class="linenos"> 9</span><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">fp</span><span class="p">)</span>
|
|
507
|
+
<span class="linenos">10</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">'Failed to open file'</span><span class="p">);</span>
|
|
508
|
+
<span class="linenos">11</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
|
|
500
509
|
</pre></div>
|
|
501
510
|
</div>
|
|
502
511
|
<p>For functions that set opaque handles through output parameters (such as <code class="docutils literal notranslate"><span class="pre">sqlite3_open_v2</span></code>), you must now use a single element array as shown below:</p>
|
|
@@ -518,24 +527,25 @@
|
|
|
518
527
|
<span class="linenos">16</span><span class="nx">sqlite3_close_v2</span><span class="p">(</span><span class="nx">db</span><span class="p">);</span>
|
|
519
528
|
</pre></div>
|
|
520
529
|
</div>
|
|
521
|
-
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.
|
|
530
|
+
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.1</span>
|
|
522
531
|
<span class="linenos"> 2</span>
|
|
523
|
-
<span class="linenos"> 3</span><span class="
|
|
524
|
-
<span class="linenos"> 4</span>
|
|
525
|
-
<span class="linenos"> 5</span
|
|
526
|
-
<span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">
|
|
527
|
-
<span class="linenos"> 7</span>
|
|
528
|
-
<span class="linenos"> 8</span
|
|
529
|
-
<span class="linenos"> 9</span><span class="kd">const</span> <span class="nx">
|
|
530
|
-
<span class="linenos">10</span>
|
|
531
|
-
<span class="linenos">11</span
|
|
532
|
-
<span class="linenos">12</span>
|
|
533
|
-
<span class="linenos">13</span
|
|
534
|
-
<span class="linenos">14</span><span class="
|
|
535
|
-
<span class="linenos">15</span
|
|
536
|
-
<span class="linenos">16</span
|
|
537
|
-
<span class="linenos">17</span>
|
|
538
|
-
<span class="linenos">18</span
|
|
532
|
+
<span class="linenos"> 3</span><span class="c1">// If you use Koffi 2.0: const sqlite3 = koffi.handle('sqlite3');</span>
|
|
533
|
+
<span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">sqlite3</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">'sqlite3'</span><span class="p">);</span>
|
|
534
|
+
<span class="linenos"> 5</span>
|
|
535
|
+
<span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</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">'int sqlite3_open_v2(const char *, _Out_ sqlite3 **db, int, const char *)'</span><span class="p">);</span>
|
|
536
|
+
<span class="linenos"> 7</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</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">'int sqlite3_close_v2(sqlite3 *db)'</span><span class="p">);</span>
|
|
537
|
+
<span class="linenos"> 8</span>
|
|
538
|
+
<span class="linenos"> 9</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">=</span> <span class="mh">0x2</span><span class="p">;</span>
|
|
539
|
+
<span class="linenos">10</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_CREATE</span> <span class="o">=</span> <span class="mh">0x4</span><span class="p">;</span>
|
|
540
|
+
<span class="linenos">11</span>
|
|
541
|
+
<span class="linenos">12</span><span class="kd">let</span> <span class="nx">db</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
542
|
+
<span class="linenos">13</span>
|
|
543
|
+
<span class="linenos">14</span><span class="kd">let</span> <span class="nx">ptr</span> <span class="o">=</span> <span class="p">[</span><span class="kc">null</span><span class="p">];</span>
|
|
544
|
+
<span class="linenos">15</span><span class="k">if</span> <span class="p">(</span><span class="nx">sqlite3_open_v2</span><span class="p">(</span><span class="s1">':memory:'</span><span class="p">,</span> <span class="nx">ptr</span><span class="p">,</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">|</span> <span class="nx">SQLITE_OPEN_CREATE</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span> <span class="o">!=</span> <span class="mf">0</span><span class="p">)</span>
|
|
545
|
+
<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">'Failed to open database'</span><span class="p">);</span>
|
|
546
|
+
<span class="linenos">17</span><span class="nx">db</span> <span class="o">=</span> <span class="nx">ptr</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span>
|
|
547
|
+
<span class="linenos">18</span>
|
|
548
|
+
<span class="linenos">19</span><span class="nx">sqlite3_close_v2</span><span class="p">(</span><span class="nx">db</span><span class="p">);</span>
|
|
539
549
|
</pre></div>
|
|
540
550
|
</div>
|
|
541
551
|
</section>
|
|
@@ -608,6 +618,7 @@
|
|
|
608
618
|
<ul>
|
|
609
619
|
<li><a class="reference internal" href="#">Changelog</a><ul>
|
|
610
620
|
<li><a class="reference internal" href="#history">History</a><ul>
|
|
621
|
+
<li><a class="reference internal" href="#koffi-2-0-1">Koffi 2.0.1</a></li>
|
|
611
622
|
<li><a class="reference internal" href="#koffi-2-0-0">Koffi 2.0.0</a></li>
|
|
612
623
|
<li><a class="reference internal" href="#koffi-1-3-12">Koffi 1.3.12</a></li>
|
|
613
624
|
<li><a class="reference internal" href="#koffi-1-3-11">Koffi 1.3.11</a></li>
|
|
@@ -630,7 +641,7 @@
|
|
|
630
641
|
<li><a class="reference internal" href="#migration-guide">Migration guide</a><ul>
|
|
631
642
|
<li><a class="reference internal" href="#koffi-1-x-to-2-x">Koffi 1.x to 2.x</a><ul>
|
|
632
643
|
<li><a class="reference internal" href="#callback-types">Callback types</a></li>
|
|
633
|
-
<li><a class="reference internal" href="#opaque-
|
|
644
|
+
<li><a class="reference internal" href="#opaque-types">Opaque types</a></li>
|
|
634
645
|
<li><a class="reference internal" href="#koffi-introspect">koffi.introspect()</a></li>
|
|
635
646
|
</ul>
|
|
636
647
|
</li>
|
|
@@ -174,8 +174,8 @@
|
|
|
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.0.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
179
|
</div>
|
|
180
180
|
</div>
|
|
181
181
|
|
|
@@ -174,8 +174,8 @@
|
|
|
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.0.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
179
|
</div>
|
|
180
180
|
</div>
|
|
181
181
|
|
|
@@ -333,7 +333,7 @@
|
|
|
333
333
|
<p>For simplicity, and because Javascript only has value semantics for primitive types, Koffi can marshal out (or in/out) two types of parameters:</p>
|
|
334
334
|
<ul class="simple">
|
|
335
335
|
<li><p><a class="reference internal" href="types#struct-types"><span class="std std-doc">Structs</span></a> (to/from JS objects)</p></li>
|
|
336
|
-
<li><p><a class="reference internal" href="types#opaque-
|
|
336
|
+
<li><p><a class="reference internal" href="types#opaque-types"><span class="std std-doc">Opaque types</span></a></p></li>
|
|
337
337
|
</ul>
|
|
338
338
|
<p>In order to change an argument from input-only to output or input/output, use the following functions:</p>
|
|
339
339
|
<ul class="simple">
|
|
@@ -370,13 +370,13 @@
|
|
|
370
370
|
</pre></div>
|
|
371
371
|
</div>
|
|
372
372
|
</section>
|
|
373
|
-
<section id="opaque-
|
|
374
|
-
<h4>Opaque
|
|
373
|
+
<section id="opaque-type-example">
|
|
374
|
+
<h4>Opaque type example<a class="headerlink" href="#opaque-type-example" title="Permalink to this heading">#</a></h4>
|
|
375
375
|
<p>This example opens an in-memory SQLite database, and uses the node-ffi-style function declaration syntax.</p>
|
|
376
376
|
<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">'koffi'</span><span class="p">);</span>
|
|
377
377
|
<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">'sqlite3.so'</span><span class="p">);</span>
|
|
378
378
|
<span class="linenos"> 3</span>
|
|
379
|
-
<span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">sqlite3</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">
|
|
379
|
+
<span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">sqlite3</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">'sqlite3'</span><span class="p">);</span>
|
|
380
380
|
<span class="linenos"> 5</span>
|
|
381
381
|
<span class="linenos"> 6</span><span class="c1">// Use koffi.out() on a double pointer to copy out (from C to JS) after the call</span>
|
|
382
382
|
<span class="linenos"> 7</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</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">'sqlite3_open_v2'</span><span class="p">,</span> <span class="s1">'int'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'str'</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">out</span><span class="p">(</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3</span><span class="p">,</span> <span class="mf">2</span><span class="p">)),</span> <span class="s1">'int'</span><span class="p">,</span> <span class="s1">'str'</span><span class="p">]);</span>
|
|
@@ -398,7 +398,7 @@
|
|
|
398
398
|
<section id="heap-allocated-values">
|
|
399
399
|
<h3>Heap-allocated values<a class="headerlink" href="#heap-allocated-values" title="Permalink to this heading">#</a></h3>
|
|
400
400
|
<p>Some C functions return heap-allocated values directly or through output parameters. While Koffi automatically converts values from C to JS (to a string or an object), it does not know when something needs to be freed, or how.</p>
|
|
401
|
-
<p>For opaque
|
|
401
|
+
<p>For opaque types, such as FILE, this does not matter because you will explicitly call <code class="docutils literal notranslate"><span class="pre">fclose()</span></code> on them. But some values (such as strings) get implicitly converted by Koffi, and you lose access to the original pointer. This creates a leak if the string is heap-allocated.</p>
|
|
402
402
|
<p>To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a <strong>disposable type</strong> with <code class="docutils literal notranslate"><span class="pre">koffi.dispose(name,</span> <span class="pre">type,</span> <span class="pre">func)</span></code>. This creates a type derived from another type, the only difference being that <em>func</em> gets called with the original pointer once the value has been converted and is not needed anymore.</p>
|
|
403
403
|
<p>The <em>name</em> can be omitted to create an anonymous disposable type. If <em>func</em> is omitted or is null, Koffi will use <code class="docutils literal notranslate"><span class="pre">koffi.free(ptr)</span></code> (which calls the standard C library <em>free</em> function under the hood).</p>
|
|
404
404
|
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">AnonHeapStr</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">'str'</span><span class="p">);</span> <span class="c1">// Anonymous type (cannot be used in function prototypes)</span>
|
|
@@ -623,7 +623,7 @@
|
|
|
623
623
|
<li><a class="reference internal" href="#c-to-js-conversion-gotchas">C to JS conversion gotchas</a><ul>
|
|
624
624
|
<li><a class="reference internal" href="#output-parameters">Output parameters</a><ul>
|
|
625
625
|
<li><a class="reference internal" href="#struct-example">Struct example</a></li>
|
|
626
|
-
<li><a class="reference internal" href="#opaque-
|
|
626
|
+
<li><a class="reference internal" href="#opaque-type-example">Opaque type example</a></li>
|
|
627
627
|
</ul>
|
|
628
628
|
</li>
|
|
629
629
|
<li><a class="reference internal" href="#heap-allocated-values">Heap-allocated values</a></li>
|
|
@@ -172,8 +172,8 @@
|
|
|
172
172
|
|
|
173
173
|
</div>
|
|
174
174
|
<div style="text-align: center; margin-top: 2em;">
|
|
175
|
+
<a href="https://www.npmjs.com/package/koffi"><img src="https://img.shields.io/badge/NPM-2.0.1-brightgreen" alt="NPM"/></a>
|
|
175
176
|
<a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
|
|
176
|
-
<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>
|
|
177
177
|
</div>
|
|
178
178
|
</div>
|
|
179
179
|
|
package/doc/dist/html/index.html
CHANGED
|
@@ -174,8 +174,8 @@
|
|
|
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.0.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
179
|
</div>
|
|
180
180
|
</div>
|
|
181
181
|
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
</div>
|
|
209
209
|
<article role="main">
|
|
210
210
|
<section id="koffi-version">
|
|
211
|
-
<h1>Koffi 2.0.
|
|
211
|
+
<h1>Koffi 2.0.1<a class="headerlink" href="#koffi-version" title="Permalink to this heading">#</a></h1>
|
|
212
212
|
<section id="overview">
|
|
213
213
|
<h2>Overview<a class="headerlink" href="#overview" title="Permalink to this heading">#</a></h2>
|
|
214
214
|
<p>Koffi is a <strong>fast and easy-to-use C FFI module for Node.js</strong>, featuring:</p>
|
|
@@ -335,7 +335,7 @@
|
|
|
335
335
|
<div class="toc-tree-container">
|
|
336
336
|
<div class="toc-tree">
|
|
337
337
|
<ul>
|
|
338
|
-
<li><a class="reference internal" href="#">Koffi 2.0.
|
|
338
|
+
<li><a class="reference internal" href="#">Koffi 2.0.1</a><ul>
|
|
339
339
|
<li><a class="reference internal" href="#overview">Overview</a></li>
|
|
340
340
|
<li><a class="reference internal" href="#table-of-contents">Table of contents</a></li>
|
|
341
341
|
<li><a class="reference internal" href="#license">License</a></li>
|
|
@@ -174,8 +174,8 @@
|
|
|
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.0.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
179
|
</div>
|
|
180
180
|
</div>
|
|
181
181
|
|
|
Binary file
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head><meta charset="utf-8"/>
|
|
4
4
|
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
5
5
|
<meta name="color-scheme" content="light dark"><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
|
|
6
|
-
<link rel="index" title="Index" href="genindex" /><link rel="search" title="Search" href="search" /><link rel="next" title="Quick start" href="start" /><link rel="prev" title="Koffi 2.0.
|
|
6
|
+
<link rel="index" title="Index" href="genindex" /><link rel="search" title="Search" href="search" /><link rel="next" title="Quick start" href="start" /><link rel="prev" title="Koffi 2.0.1" href="index" />
|
|
7
7
|
|
|
8
8
|
<meta name="generator" content="sphinx-5.0.1, furo 2022.06.04.1"/>
|
|
9
9
|
<title>Requirements - Koffi</title>
|
|
@@ -174,8 +174,8 @@
|
|
|
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.0.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
179
|
</div>
|
|
180
180
|
</div>
|
|
181
181
|
|
|
@@ -171,8 +171,8 @@
|
|
|
171
171
|
|
|
172
172
|
</div>
|
|
173
173
|
<div style="text-align: center; margin-top: 2em;">
|
|
174
|
+
<a href="https://www.npmjs.com/package/koffi"><img src="https://img.shields.io/badge/NPM-2.0.1-brightgreen" alt="NPM"/></a>
|
|
174
175
|
<a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
|
|
175
|
-
<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>
|
|
176
176
|
</div>
|
|
177
177
|
</div>
|
|
178
178
|
|