koffi 2.0.0 → 2.0.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/ChangeLog.md +8 -2
- 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
- package/doc/benchmarks.md +2 -2
- package/doc/changes.md +12 -12
- package/doc/conf.py +14 -1
- package/doc/dist/doctrees/benchmarks.doctree +0 -0
- 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/.buildinfo +1 -1
- package/doc/dist/html/_sources/benchmarks.md.txt +2 -2
- package/doc/dist/html/_sources/changes.md.txt +12 -12
- package/doc/dist/html/_sources/functions.md.txt +6 -6
- package/doc/dist/html/_sources/types.md.txt +10 -2
- package/doc/dist/html/benchmarks.html +6 -2
- package/doc/dist/html/changes.html +18 -14
- package/doc/dist/html/contribute.html +4 -0
- package/doc/dist/html/functions.html +10 -6
- package/doc/dist/html/genindex.html +4 -0
- package/doc/dist/html/index.html +8 -4
- package/doc/dist/html/memory.html +4 -0
- package/doc/dist/html/objects.inv +0 -0
- package/doc/dist/html/platforms.html +5 -1
- package/doc/dist/html/search.html +4 -0
- package/doc/dist/html/searchindex.js +1 -1
- package/doc/dist/html/start.html +4 -0
- package/doc/dist/html/types.html +20 -4
- package/doc/functions.md +6 -6
- package/doc/templates/badges.html +5 -0
- package/doc/types.md +11 -3
- package/package.json +1 -1
- package/src/abi_arm32.cc +1 -1
- package/src/abi_arm64.cc +1 -1
- package/src/abi_riscv64.cc +1 -1
- package/src/abi_x64_sysv.cc +1 -1
- package/src/abi_x64_win.cc +1 -1
- package/src/abi_x86.cc +1 -1
- package/src/ffi.cc +3 -3
- package/test/sqlite.js +5 -5
- package/test/sync.js +3 -1
- package/build/qemu/2.0.0/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.0.0/koffi_win32_x64.tar.gz +0 -0
package/ChangeLog.md
CHANGED
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## History
|
|
4
4
|
|
|
5
|
+
### Koffi 2.0.1
|
|
6
|
+
|
|
7
|
+
**Main changes:**
|
|
8
|
+
|
|
9
|
+
- Return `undefined` (instead of null) for `void` functions
|
|
10
|
+
|
|
5
11
|
### Koffi 2.0.0
|
|
6
12
|
|
|
7
13
|
**Major new features:**
|
|
8
14
|
|
|
9
|
-
- Add disposable types for automatic disposal of C values (such as heap-allocated strings)
|
|
10
|
-
- Add support for registered callbacks, that can be called after the initial FFI call
|
|
15
|
+
- Add [disposable types](functions.md#heap-allocated-values) for automatic disposal of C values (such as heap-allocated strings)
|
|
16
|
+
- Add support for [registered callbacks](functions.md#registered-callbacks), that can be called after the initial FFI call
|
|
11
17
|
- Support named pointer types
|
|
12
18
|
- Support complex type specifications outside of prototype parser
|
|
13
19
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/doc/benchmarks.md
CHANGED
|
@@ -10,8 +10,8 @@ Here is a quick overview of the execution time of Koffi calls on three benchmark
|
|
|
10
10
|
|
|
11
11
|
<table style="margin: 0 auto;">
|
|
12
12
|
<tr>
|
|
13
|
-
<td><a href="
|
|
14
|
-
<td><a href="
|
|
13
|
+
<td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
|
|
14
|
+
<td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
|
|
15
15
|
</tr>
|
|
16
16
|
</table>
|
|
17
17
|
|
package/doc/changes.md
CHANGED
|
@@ -76,10 +76,10 @@ For functions that return handles or pass them by parameter:
|
|
|
76
76
|
// Koffi 1.x
|
|
77
77
|
|
|
78
78
|
const FILE = koffi.handle('FILE');
|
|
79
|
-
const fopen = lib.func('
|
|
80
|
-
const
|
|
79
|
+
const fopen = lib.func('fopen', 'FILE', ['str', 'str']);
|
|
80
|
+
const fopen = lib.func('fclose', 'int', ['FILE']);
|
|
81
81
|
|
|
82
|
-
let fp = fopen('
|
|
82
|
+
let fp = fopen('EMPTY', 'wb');
|
|
83
83
|
if (!fp)
|
|
84
84
|
throw new Error('Failed to open file');
|
|
85
85
|
fclose(fp);
|
|
@@ -89,10 +89,10 @@ fclose(fp);
|
|
|
89
89
|
// Koffi 2.x
|
|
90
90
|
|
|
91
91
|
const FILE = koffi.handle('FILE');
|
|
92
|
-
const fopen = lib.func('
|
|
93
|
-
const
|
|
92
|
+
const fopen = lib.func('fopen', 'FILE *', ['str', 'str']);
|
|
93
|
+
const fopen = lib.func('fclose', 'int', ['FILE *']);
|
|
94
94
|
|
|
95
|
-
let fp = fopen('
|
|
95
|
+
let fp = fopen('EMPTY', 'wb');
|
|
96
96
|
if (!fp)
|
|
97
97
|
throw new Error('Failed to open file');
|
|
98
98
|
fclose(fp);
|
|
@@ -103,10 +103,10 @@ For functions that set opaque handles through output parameters (such as `sqlite
|
|
|
103
103
|
```js
|
|
104
104
|
// Koffi 1.x
|
|
105
105
|
|
|
106
|
-
const
|
|
106
|
+
const sqlite3 = koffi.handle('sqlite3');
|
|
107
107
|
|
|
108
|
-
const sqlite3_open_v2 = lib.func('sqlite3_open_v2
|
|
109
|
-
const sqlite3_close_v2 = lib.func('sqlite3_close_v2
|
|
108
|
+
const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 *db, int, const char *)');
|
|
109
|
+
const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 db)');
|
|
110
110
|
|
|
111
111
|
const SQLITE_OPEN_READWRITE = 0x2;
|
|
112
112
|
const SQLITE_OPEN_CREATE = 0x4;
|
|
@@ -122,10 +122,10 @@ sqlite3_close_v2(db);
|
|
|
122
122
|
```js
|
|
123
123
|
// Koffi 2.x
|
|
124
124
|
|
|
125
|
-
const
|
|
125
|
+
const sqlite3 = koffi.handle('sqlite3');
|
|
126
126
|
|
|
127
|
-
const sqlite3_open_v2 = lib.func('sqlite3_open_v2
|
|
128
|
-
const sqlite3_close_v2 = lib.func('
|
|
127
|
+
const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 **db, int, const char *)');
|
|
128
|
+
const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 *db)');
|
|
129
129
|
|
|
130
130
|
const SQLITE_OPEN_READWRITE = 0x2;
|
|
131
131
|
const SQLITE_OPEN_CREATE = 0x4;
|
package/doc/conf.py
CHANGED
|
@@ -21,7 +21,7 @@ extensions = [
|
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
# Add any paths that contain templates here, relative to this directory.
|
|
24
|
-
templates_path = ['
|
|
24
|
+
templates_path = ['templates']
|
|
25
25
|
|
|
26
26
|
exclude_patterns = []
|
|
27
27
|
|
|
@@ -48,6 +48,19 @@ html_link_suffix = ''
|
|
|
48
48
|
|
|
49
49
|
html_css_files = ['custom.css']
|
|
50
50
|
|
|
51
|
+
html_sidebars = {
|
|
52
|
+
"**": [
|
|
53
|
+
"sidebar/brand.html",
|
|
54
|
+
"sidebar/search.html",
|
|
55
|
+
"sidebar/scroll-start.html",
|
|
56
|
+
"sidebar/navigation.html",
|
|
57
|
+
"sidebar/ethical-ads.html",
|
|
58
|
+
"badges.html",
|
|
59
|
+
"sidebar/scroll-end.html",
|
|
60
|
+
"sidebar/variant-selector.html"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
|
|
51
64
|
# -- MyST parser options -------------------------------------------------
|
|
52
65
|
|
|
53
66
|
myst_enable_extensions = [
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/doc/dist/html/.buildinfo
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# Sphinx build info version 1
|
|
2
2
|
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
|
3
|
-
config:
|
|
3
|
+
config: 176d11a9c5f53cb77e2388cfd78b9cee
|
|
4
4
|
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
|
@@ -10,8 +10,8 @@ Here is a quick overview of the execution time of Koffi calls on three benchmark
|
|
|
10
10
|
|
|
11
11
|
<table style="margin: 0 auto;">
|
|
12
12
|
<tr>
|
|
13
|
-
<td><a href="
|
|
14
|
-
<td><a href="
|
|
13
|
+
<td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
|
|
14
|
+
<td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
|
|
15
15
|
</tr>
|
|
16
16
|
</table>
|
|
17
17
|
|
|
@@ -76,10 +76,10 @@ For functions that return handles or pass them by parameter:
|
|
|
76
76
|
// Koffi 1.x
|
|
77
77
|
|
|
78
78
|
const FILE = koffi.handle('FILE');
|
|
79
|
-
const fopen = lib.func('
|
|
80
|
-
const
|
|
79
|
+
const fopen = lib.func('fopen', 'FILE', ['str', 'str']);
|
|
80
|
+
const fopen = lib.func('fclose', 'int', ['FILE']);
|
|
81
81
|
|
|
82
|
-
let fp = fopen('
|
|
82
|
+
let fp = fopen('EMPTY', 'wb');
|
|
83
83
|
if (!fp)
|
|
84
84
|
throw new Error('Failed to open file');
|
|
85
85
|
fclose(fp);
|
|
@@ -89,10 +89,10 @@ fclose(fp);
|
|
|
89
89
|
// Koffi 2.x
|
|
90
90
|
|
|
91
91
|
const FILE = koffi.handle('FILE');
|
|
92
|
-
const fopen = lib.func('
|
|
93
|
-
const
|
|
92
|
+
const fopen = lib.func('fopen', 'FILE *', ['str', 'str']);
|
|
93
|
+
const fopen = lib.func('fclose', 'int', ['FILE *']);
|
|
94
94
|
|
|
95
|
-
let fp = fopen('
|
|
95
|
+
let fp = fopen('EMPTY', 'wb');
|
|
96
96
|
if (!fp)
|
|
97
97
|
throw new Error('Failed to open file');
|
|
98
98
|
fclose(fp);
|
|
@@ -103,10 +103,10 @@ For functions that set opaque handles through output parameters (such as `sqlite
|
|
|
103
103
|
```js
|
|
104
104
|
// Koffi 1.x
|
|
105
105
|
|
|
106
|
-
const
|
|
106
|
+
const sqlite3 = koffi.handle('sqlite3');
|
|
107
107
|
|
|
108
|
-
const sqlite3_open_v2 = lib.func('sqlite3_open_v2
|
|
109
|
-
const sqlite3_close_v2 = lib.func('sqlite3_close_v2
|
|
108
|
+
const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 *db, int, const char *)');
|
|
109
|
+
const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 db)');
|
|
110
110
|
|
|
111
111
|
const SQLITE_OPEN_READWRITE = 0x2;
|
|
112
112
|
const SQLITE_OPEN_CREATE = 0x4;
|
|
@@ -122,10 +122,10 @@ sqlite3_close_v2(db);
|
|
|
122
122
|
```js
|
|
123
123
|
// Koffi 2.x
|
|
124
124
|
|
|
125
|
-
const
|
|
125
|
+
const sqlite3 = koffi.handle('sqlite3');
|
|
126
126
|
|
|
127
|
-
const sqlite3_open_v2 = lib.func('sqlite3_open_v2
|
|
128
|
-
const sqlite3_close_v2 = lib.func('
|
|
127
|
+
const sqlite3_open_v2 = lib.func('int sqlite3_open_v2(const char *, _Out_ sqlite3 **db, int, const char *)');
|
|
128
|
+
const sqlite3_close_v2 = lib.func('int sqlite3_close_v2(sqlite3 *db)');
|
|
129
129
|
|
|
130
130
|
const SQLITE_OPEN_READWRITE = 0x2;
|
|
131
131
|
const SQLITE_OPEN_CREATE = 0x4;
|
|
@@ -160,11 +160,11 @@ This example opens an in-memory SQLite database, and uses the node-ffi-style fun
|
|
|
160
160
|
const koffi = require('koffi');
|
|
161
161
|
const lib = koffi.load('sqlite3.so');
|
|
162
162
|
|
|
163
|
-
const
|
|
163
|
+
const sqlite3 = koffi.handle('sqlite3');
|
|
164
164
|
|
|
165
165
|
// Use koffi.out() on a double pointer to copy out (from C to JS) after the call
|
|
166
|
-
const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(koffi.pointer(
|
|
167
|
-
const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [koffi.pointer(
|
|
166
|
+
const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(koffi.pointer(sqlite3, 2)), 'int', 'str']);
|
|
167
|
+
const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [koffi.pointer(sqlite3)]);
|
|
168
168
|
|
|
169
169
|
const SQLITE_OPEN_READWRITE = 0x2;
|
|
170
170
|
const SQLITE_OPEN_CREATE = 0x4;
|
|
@@ -183,7 +183,7 @@ Some C functions return heap-allocated values directly or through output paramet
|
|
|
183
183
|
|
|
184
184
|
For opaque handles, such as FILE, this does not matter because you will explicitly call `fclose()` 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.
|
|
185
185
|
|
|
186
|
-
To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a disposable type with `koffi.dispose(name, type, func)`. This creates a type derived from another type, the only difference being that *func* gets called with the original pointer once the value has been converted and is not needed anymore.
|
|
186
|
+
To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a **disposable type** with `koffi.dispose(name, type, func)`. This creates a type derived from another type, the only difference being that *func* gets called with the original pointer once the value has been converted and is not needed anymore.
|
|
187
187
|
|
|
188
188
|
The *name* can be omitted to create an anonymous disposable type. If *func* is omitted or is null, Koffi will use `koffi.free(ptr)` (which calls the standard C library *free* function under the hood).
|
|
189
189
|
|
|
@@ -199,7 +199,7 @@ The following example illustrates the use of a disposable type derived from *str
|
|
|
199
199
|
const koffi = require('koffi');
|
|
200
200
|
const lib = koffi.load('libc.so.6');
|
|
201
201
|
|
|
202
|
-
// You can also use: const strdup = lib.func('const char *!
|
|
202
|
+
// You can also use: const strdup = lib.func('const char *! strdup(const char *str)')
|
|
203
203
|
const HeapStr = koffi.disposable('str');
|
|
204
204
|
const strdup = lib.cdecl('strdup', HeapStr, ['str']);
|
|
205
205
|
|
|
@@ -207,7 +207,7 @@ let copy = strdup('Hello!');
|
|
|
207
207
|
console.log(copy); // Prints Hello!
|
|
208
208
|
```
|
|
209
209
|
|
|
210
|
-
When you declare functions with the [prototype-like syntax](#c-like-prototypes), you can either use named
|
|
210
|
+
When you declare functions with the [prototype-like syntax](#c-like-prototypes), you can either use named disposable types or use the '!' shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls `koffi.free(ptr)`.
|
|
211
211
|
|
|
212
212
|
```js
|
|
213
213
|
const koffi = require('koffi');
|
|
@@ -515,7 +515,15 @@ Koffi can also convert JS strings to fixed-sized arrays in the following cases:
|
|
|
515
515
|
|
|
516
516
|
The reverse case is also true, Koffi can convert a C fixed-size buffer to a JS string. This happens by default for char, char16 and char16_t arrays, but you can also explicitly ask for this with the `string` array hint (e.g. `koffi.array('char', 8, 'string')`).
|
|
517
517
|
|
|
518
|
-
##
|
|
518
|
+
## Disposable types
|
|
519
|
+
|
|
520
|
+
Disposable types allow you to register a function that will automatically called after each C to JS conversion performed by Koffi. This can be used to avoid leaking heap-allocated strings, for example.
|
|
521
|
+
|
|
522
|
+
Read the documentation for [disposable types](functions.md#heap-allocated-values) on the page about function calls.
|
|
523
|
+
|
|
524
|
+
## Utility functions
|
|
525
|
+
|
|
526
|
+
### Type introspection
|
|
519
527
|
|
|
520
528
|
Koffi exposes three functions to explore type information:
|
|
521
529
|
|
|
@@ -540,6 +548,6 @@ console.log(koffi.sizeof('long'));
|
|
|
540
548
|
console.log(koffi.sizeof(koffi.types.long));
|
|
541
549
|
```
|
|
542
550
|
|
|
543
|
-
|
|
551
|
+
### Type aliases
|
|
544
552
|
|
|
545
553
|
You can alias a type with `koffi.alias(name, type)`. Aliased types are completely equivalent.
|
|
@@ -172,6 +172,10 @@
|
|
|
172
172
|
<li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
|
|
173
173
|
</ul>
|
|
174
174
|
|
|
175
|
+
</div>
|
|
176
|
+
<div style="text-align: center; margin-top: 2em;">
|
|
177
|
+
<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>
|
|
175
179
|
</div>
|
|
176
180
|
</div>
|
|
177
181
|
|
|
@@ -215,8 +219,8 @@
|
|
|
215
219
|
</ul>
|
|
216
220
|
<table style="margin: 0 auto;">
|
|
217
221
|
<tr>
|
|
218
|
-
<td><a href="
|
|
219
|
-
<td><a href="
|
|
222
|
+
<td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
|
|
223
|
+
<td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
|
|
220
224
|
</tr>
|
|
221
225
|
</table>
|
|
222
226
|
<p>These results are detailed and explained below, and compared to node-ffi/node-ffi-napi.</p>
|
|
@@ -172,6 +172,10 @@
|
|
|
172
172
|
<li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Changelog</a></li>
|
|
173
173
|
</ul>
|
|
174
174
|
|
|
175
|
+
</div>
|
|
176
|
+
<div style="text-align: center; margin-top: 2em;">
|
|
177
|
+
<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>
|
|
175
179
|
</div>
|
|
176
180
|
</div>
|
|
177
181
|
|
|
@@ -211,8 +215,8 @@
|
|
|
211
215
|
<h3>Koffi 2.0.0<a class="headerlink" href="#koffi-2-0-0" title="Permalink to this heading">#</a></h3>
|
|
212
216
|
<p><strong>Major new features:</strong></p>
|
|
213
217
|
<ul class="simple">
|
|
214
|
-
<li><p>Add disposable types for automatic disposal of C values (such as heap-allocated strings)</p></li>
|
|
215
|
-
<li><p>Add support for registered callbacks
|
|
218
|
+
<li><p>Add <a class="reference internal" href="functions#heap-allocated-values"><span class="std std-doc">disposable types</span></a> for automatic disposal of C values (such as heap-allocated strings)</p></li>
|
|
219
|
+
<li><p>Add support for <a class="reference internal" href="functions#registered-callbacks"><span class="std std-doc">registered callbacks</span></a>, that can be called after the initial FFI call</p></li>
|
|
216
220
|
<li><p>Support named pointer types</p></li>
|
|
217
221
|
<li><p>Support complex type specifications outside of prototype parser</p></li>
|
|
218
222
|
</ul>
|
|
@@ -474,10 +478,10 @@
|
|
|
474
478
|
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
|
|
475
479
|
<span class="linenos"> 2</span>
|
|
476
480
|
<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>
|
|
477
|
-
<span class="linenos"> 4</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">'FILE
|
|
478
|
-
<span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">
|
|
481
|
+
<span class="linenos"> 4</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>
|
|
482
|
+
<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">'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>
|
|
479
483
|
<span class="linenos"> 6</span>
|
|
480
|
-
<span class="linenos"> 7</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">'
|
|
484
|
+
<span class="linenos"> 7</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>
|
|
481
485
|
<span class="linenos"> 8</span><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">fp</span><span class="p">)</span>
|
|
482
486
|
<span class="linenos"> 9</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>
|
|
483
487
|
<span class="linenos">10</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
|
|
@@ -486,10 +490,10 @@
|
|
|
486
490
|
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.x</span>
|
|
487
491
|
<span class="linenos"> 2</span>
|
|
488
492
|
<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>
|
|
489
|
-
<span class="linenos"> 4</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">'FILE
|
|
490
|
-
<span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">
|
|
493
|
+
<span class="linenos"> 4</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>
|
|
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">'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>
|
|
491
495
|
<span class="linenos"> 6</span>
|
|
492
|
-
<span class="linenos"> 7</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">'
|
|
496
|
+
<span class="linenos"> 7</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>
|
|
493
497
|
<span class="linenos"> 8</span><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">fp</span><span class="p">)</span>
|
|
494
498
|
<span class="linenos"> 9</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>
|
|
495
499
|
<span class="linenos">10</span><span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
|
|
@@ -498,10 +502,10 @@
|
|
|
498
502
|
<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>
|
|
499
503
|
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 1.x</span>
|
|
500
504
|
<span class="linenos"> 2</span>
|
|
501
|
-
<span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">
|
|
505
|
+
<span class="linenos"> 3</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">handle</span><span class="p">(</span><span class="s1">'sqlite3'</span><span class="p">);</span>
|
|
502
506
|
<span class="linenos"> 4</span>
|
|
503
|
-
<span class="linenos"> 5</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">'
|
|
504
|
-
<span class="linenos"> 6</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">'sqlite3_close_v2
|
|
507
|
+
<span class="linenos"> 5</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>
|
|
508
|
+
<span class="linenos"> 6</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>
|
|
505
509
|
<span class="linenos"> 7</span>
|
|
506
510
|
<span class="linenos"> 8</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>
|
|
507
511
|
<span class="linenos"> 9</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>
|
|
@@ -516,10 +520,10 @@
|
|
|
516
520
|
</div>
|
|
517
521
|
<div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// Koffi 2.x</span>
|
|
518
522
|
<span class="linenos"> 2</span>
|
|
519
|
-
<span class="linenos"> 3</span><span class="kd">const</span> <span class="nx">
|
|
523
|
+
<span class="linenos"> 3</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">handle</span><span class="p">(</span><span class="s1">'sqlite3'</span><span class="p">);</span>
|
|
520
524
|
<span class="linenos"> 4</span>
|
|
521
|
-
<span class="linenos"> 5</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">'
|
|
522
|
-
<span class="linenos"> 6</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">'sqlite3_close_v2
|
|
525
|
+
<span class="linenos"> 5</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>
|
|
526
|
+
<span class="linenos"> 6</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>
|
|
523
527
|
<span class="linenos"> 7</span>
|
|
524
528
|
<span class="linenos"> 8</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>
|
|
525
529
|
<span class="linenos"> 9</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>
|
|
@@ -172,6 +172,10 @@
|
|
|
172
172
|
<li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
|
|
173
173
|
</ul>
|
|
174
174
|
|
|
175
|
+
</div>
|
|
176
|
+
<div style="text-align: center; margin-top: 2em;">
|
|
177
|
+
<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>
|
|
175
179
|
</div>
|
|
176
180
|
</div>
|
|
177
181
|
|
|
@@ -172,6 +172,10 @@
|
|
|
172
172
|
<li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
|
|
173
173
|
</ul>
|
|
174
174
|
|
|
175
|
+
</div>
|
|
176
|
+
<div style="text-align: center; margin-top: 2em;">
|
|
177
|
+
<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>
|
|
175
179
|
</div>
|
|
176
180
|
</div>
|
|
177
181
|
|
|
@@ -372,11 +376,11 @@
|
|
|
372
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>
|
|
373
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>
|
|
374
378
|
<span class="linenos"> 3</span>
|
|
375
|
-
<span class="linenos"> 4</span><span class="kd">const</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">handle</span><span class="p">(</span><span class="s1">'sqlite3'</span><span class="p">);</span>
|
|
376
380
|
<span class="linenos"> 5</span>
|
|
377
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>
|
|
378
|
-
<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">
|
|
379
|
-
<span class="linenos"> 8</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">'sqlite3_close_v2'</span><span class="p">,</span> <span class="s1">'int'</span><span class="p">,</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">
|
|
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>
|
|
383
|
+
<span class="linenos"> 8</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">'sqlite3_close_v2'</span><span class="p">,</span> <span class="s1">'int'</span><span class="p">,</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>
|
|
380
384
|
<span class="linenos"> 9</span>
|
|
381
385
|
<span class="linenos">10</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>
|
|
382
386
|
<span class="linenos">11</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>
|
|
@@ -395,7 +399,7 @@
|
|
|
395
399
|
<h3>Heap-allocated values<a class="headerlink" href="#heap-allocated-values" title="Permalink to this heading">#</a></h3>
|
|
396
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>
|
|
397
401
|
<p>For opaque handles, 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>
|
|
398
|
-
<p>To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a disposable type 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>
|
|
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>
|
|
399
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>
|
|
400
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>
|
|
401
405
|
<span class="linenos">2</span><span class="kd">const</span> <span class="nx">NamedHeapStr</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">'HeapStr'</span><span class="p">,</span> <span class="s1">'str'</span><span class="p">);</span> <span class="c1">// Same thing, but named so usable in function prototypes</span>
|
|
@@ -406,7 +410,7 @@
|
|
|
406
410
|
<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>
|
|
407
411
|
<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">'libc.so.6'</span><span class="p">);</span>
|
|
408
412
|
<span class="linenos">3</span>
|
|
409
|
-
<span class="linenos">4</span><span class="c1">// You can also use: const strdup = lib.func('const char *!
|
|
413
|
+
<span class="linenos">4</span><span class="c1">// You can also use: const strdup = lib.func('const char *! strdup(const char *str)')</span>
|
|
410
414
|
<span class="linenos">5</span><span class="kd">const</span> <span class="nx">HeapStr</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>
|
|
411
415
|
<span class="linenos">6</span><span class="kd">const</span> <span class="nx">strdup</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">cdecl</span><span class="p">(</span><span class="s1">'strdup'</span><span class="p">,</span> <span class="nx">HeapStr</span><span class="p">,</span> <span class="p">[</span><span class="s1">'str'</span><span class="p">]);</span>
|
|
412
416
|
<span class="linenos">7</span>
|
|
@@ -414,7 +418,7 @@
|
|
|
414
418
|
<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">copy</span><span class="p">);</span> <span class="c1">// Prints Hello!</span>
|
|
415
419
|
</pre></div>
|
|
416
420
|
</div>
|
|
417
|
-
<p>When you declare functions with the <a class="reference internal" href="#c-like-prototypes"><span class="std std-doc">prototype-like syntax</span></a>, you can either use named
|
|
421
|
+
<p>When you declare functions with the <a class="reference internal" href="#c-like-prototypes"><span class="std std-doc">prototype-like syntax</span></a>, you can either use named disposable types or use the ‘!’ shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls <code class="docutils literal notranslate"><span class="pre">koffi.free(ptr)</span></code>.</p>
|
|
418
422
|
<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>
|
|
419
423
|
<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">'libc.so.6'</span><span class="p">);</span>
|
|
420
424
|
<span class="linenos">3</span>
|
|
@@ -170,6 +170,10 @@
|
|
|
170
170
|
<li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
|
|
171
171
|
</ul>
|
|
172
172
|
|
|
173
|
+
</div>
|
|
174
|
+
<div style="text-align: center; margin-top: 2em;">
|
|
175
|
+
<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>
|
|
173
177
|
</div>
|
|
174
178
|
</div>
|
|
175
179
|
|