koffi 2.5.21-beta.3 → 2.6.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.
- package/CHANGELOG.md +15 -0
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm32hf/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_riscv64hf64/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/callbacks.md +2 -16
- package/doc/functions.md +16 -0
- package/doc/index.rst +1 -0
- package/doc/polymorphism.md +1 -1
- package/doc/variables.md +100 -0
- package/package.json +2 -2
- package/src/index.js +2 -2
- package/src/koffi/src/ffi.cc +15 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## Version history
|
|
4
4
|
|
|
5
|
+
### Koffi 2.6
|
|
6
|
+
|
|
7
|
+
#### Koffi 2.6.0 (2023-09-13)
|
|
8
|
+
|
|
9
|
+
**New features:**
|
|
10
|
+
|
|
11
|
+
- Use [koffi.symbol()](variables.md#variable-definitions) to make pointers to exported variables (or other symbols)
|
|
12
|
+
- Use [koffi.encode()](variables.md#encode-to-c-memory) to explictly encode data from JS to C memory
|
|
13
|
+
- Use shared library [lazy-loading](functions.md#loading-options) (RTLD_LAZY) on POSIX platforms
|
|
14
|
+
|
|
15
|
+
**Other changes:**
|
|
16
|
+
|
|
17
|
+
- Print more helpful error for Win32/Win64 DLL mismatches
|
|
18
|
+
- Add missing 'Union' primitive value in TS definition file
|
|
19
|
+
|
|
5
20
|
### Koffi 2.5
|
|
6
21
|
|
|
7
22
|
#### Koffi 2.5.20 (2023-08-31)
|
|
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/callbacks.md
CHANGED
|
@@ -153,14 +153,9 @@ let cb2 = koffi.register(store, store.get, 'IntCallback *'); // However in this
|
|
|
153
153
|
|
|
154
154
|
Koffi does not have enough information to convert callback pointer arguments to an appropriate JS value. In this case, your JS function will receive an opaque *External* object.
|
|
155
155
|
|
|
156
|
-
You can pass this value through to another C function that expects a pointer of the same type, or you can use
|
|
156
|
+
You can pass this value through to another C function that expects a pointer of the same type, or you can use [koffi.decode()](variables.md#decode-to-js-values) function to decode pointer arguments.
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
- `koffi.decode(value, type)`: no offset, expect NUL-terminated strings
|
|
161
|
-
- `koffi.decode(value, offset, type)`: explicit offset to add to the pointer before decoding
|
|
162
|
-
|
|
163
|
-
The following example sorts an array of strings (in-place) with `qsort()`:
|
|
158
|
+
The following examples uses it to sort an array of strings in-place with the standard C function `qsort()`:
|
|
164
159
|
|
|
165
160
|
```js
|
|
166
161
|
// ES6 syntax: import koffi from 'koffi';
|
|
@@ -183,15 +178,6 @@ qsort(koffi.as(array, 'char **'), array.length, koffi.sizeof('void *'), (ptr1, p
|
|
|
183
178
|
console.log(array); // Prints ['123', 'bar', 'foo', 'foobar']
|
|
184
179
|
```
|
|
185
180
|
|
|
186
|
-
There is also an optional ending `length` argument that you can use in two cases:
|
|
187
|
-
|
|
188
|
-
- Use it to give the number of bytes to decode in non-NUL terminated strings: `koffi.decode(value, 'char *', 5)`
|
|
189
|
-
- Decode consecutive values into an array. For example, here is how you can decode an array with 3 float values: `koffi.decode(value, 'float', 3)`. This is equivalent to `koffi.decode(value, koffi.array('float', 3))`.
|
|
190
|
-
|
|
191
|
-
```{note}
|
|
192
|
-
In Koffi 2.2 and earlier versions, the length argument is only used to decode strings and is ignored otherwise.
|
|
193
|
-
```
|
|
194
|
-
|
|
195
181
|
### Asynchronous callbacks
|
|
196
182
|
|
|
197
183
|
*New in Koffi 2.2.2*
|
package/doc/functions.md
CHANGED
|
@@ -19,6 +19,22 @@ Starting with *Koffi 2.3.20*, you can explicitly unload a library by calling `li
|
|
|
19
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
20
|
```
|
|
21
21
|
|
|
22
|
+
## Loading options
|
|
23
|
+
|
|
24
|
+
*New in Koffi 2.6*
|
|
25
|
+
|
|
26
|
+
The `load` function can take an optional object argument, with the following options:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
const options = {
|
|
30
|
+
lazy: true // Use RTLD_LAZY (lazy-binding) on POSIX platforms (by default, use RTLD_NOW)
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const lib = koffi.load('/path/to/shared/library.so', options);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
More options may be added if needed.
|
|
37
|
+
|
|
22
38
|
## Function definitions
|
|
23
39
|
|
|
24
40
|
### Definition syntax
|
package/doc/index.rst
CHANGED
package/doc/polymorphism.md
CHANGED
|
@@ -105,4 +105,4 @@ console.log(vec1); // { x: 3, y: 2, z: 1 }
|
|
|
105
105
|
console.log(vec2); // { x: 1, y: 2, z: 3 }
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
See [
|
|
108
|
+
See [decoding variables](variables.md#decode-to-js-values) for more information about the decode function.
|
package/doc/variables.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Exported variables
|
|
2
|
+
|
|
3
|
+
## Variable definitions
|
|
4
|
+
|
|
5
|
+
*New in Koffi 2.6*
|
|
6
|
+
|
|
7
|
+
To find an exported and declare a variable, use `lib.symbol(name, type)`. You need to specify its name and its type.
|
|
8
|
+
|
|
9
|
+
```c
|
|
10
|
+
int my_int = 42;
|
|
11
|
+
const char *my_string = NULL;
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
const my_int = lib.symbol('my_int', 'int');
|
|
16
|
+
const my_string = lib.symbol('my_string', 'const char *');
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
You cannot directly manipulate these variables, use:
|
|
20
|
+
|
|
21
|
+
- [koffi.decode()](#decode-to-js-values) to read their value
|
|
22
|
+
- [koffi.encode()](#encode-to-c-memory) to change their valuèe
|
|
23
|
+
|
|
24
|
+
## Decode to JS values
|
|
25
|
+
|
|
26
|
+
*New in Koffi 2.2, changed in Koffi 2.3*
|
|
27
|
+
|
|
28
|
+
Use `koffi.decode()` to decode C pointers, wrapped as external objects or as simple numbers.
|
|
29
|
+
|
|
30
|
+
Some arguments are optional and this function can be called in several ways:
|
|
31
|
+
|
|
32
|
+
- `koffi.decode(value, type)`: no offset
|
|
33
|
+
- `koffi.decode(value, offset, type)`: explicit offset to add to the pointer before decoding
|
|
34
|
+
|
|
35
|
+
By default, Koffi expects NUL terminated strings when decoding them. See below if you need to specify the string length.
|
|
36
|
+
|
|
37
|
+
The following example illustrates how to decode an integer and a C string variable.
|
|
38
|
+
|
|
39
|
+
```c
|
|
40
|
+
int my_int = 42;
|
|
41
|
+
const char *my_string = "foobar";
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const my_int = lib.symbol('my_int', 'int');
|
|
46
|
+
const my_string = lib.symbol('my_string', 'const char *');
|
|
47
|
+
|
|
48
|
+
console.log(koffi.decode(my_int, 'int')) // Prints 42
|
|
49
|
+
console.log(koffi.decode(my_string, 'const char *')) // Prints "foobar"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
There is also an optional ending `length` argument that you can use in two cases:
|
|
53
|
+
|
|
54
|
+
- Use it to give the number of bytes to decode in non-NUL terminated strings: `koffi.decode(value, 'char *', 5)`
|
|
55
|
+
- Decode consecutive values into an array. For example, here is how you can decode an array with 3 float values: `koffi.decode(value, 'float', 3)`. This is equivalent to `koffi.decode(value, koffi.array('float', 3))`.
|
|
56
|
+
|
|
57
|
+
Thge example below will decode the symbol `my_string` defined above but only the first three bytes.
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
// Only decode 3 bytes from the C string my_string
|
|
61
|
+
console.log(koffi.decode(my_string, 'const char *', 3)) // Prints "foo"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```{note}
|
|
65
|
+
In Koffi 2.2 and earlier versions, the length argument is only used to decode strings and is ignored otherwise.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Encode to C memory
|
|
69
|
+
|
|
70
|
+
*New in Koffi 2.6*
|
|
71
|
+
|
|
72
|
+
Use `koffi.encode()` to encode C pointers, wrapped as external objects or as simple numbers.
|
|
73
|
+
|
|
74
|
+
Some arguments are optional and this function can be called in several ways:
|
|
75
|
+
|
|
76
|
+
- `koffi.encode(ref, type, value)`: no offset
|
|
77
|
+
- `koffi.encode(ref, offset, type, value)`: explicit offset to add to the pointer before encoding
|
|
78
|
+
|
|
79
|
+
We'll reuse the examples shown above and change the variable values with `koffi.encode()`.
|
|
80
|
+
|
|
81
|
+
```c
|
|
82
|
+
int my_int = 42;
|
|
83
|
+
const char *my_string = NULL;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
const my_int = lib.symbol('my_int', 'int');
|
|
88
|
+
const my_string = lib.symbol('my_string', 'const char *');
|
|
89
|
+
|
|
90
|
+
console.log(koffi.decode(my_int, 'int')) // Prints 42
|
|
91
|
+
console.log(koffi.decode(my_string, 'const char *')) // Prints null
|
|
92
|
+
|
|
93
|
+
koffi.encode(my_int, 'int', -1);
|
|
94
|
+
koffi.encode(my_string, 'const char *', 'Hello World!');
|
|
95
|
+
|
|
96
|
+
console.log(koffi.decode(my_int, 'int')) // Prints -1
|
|
97
|
+
console.log(koffi.decode(my_string, 'const char *')) // Prints "Hello World!"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
When encoding strings (either directly or embedded in arrays or structs), the memory will be bound to the raw pointer value and managed by Koffi. You can assign to the same string again and again with any leak or risk of use-after-free.
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -378,8 +378,8 @@ var require_package = __commonJS({
|
|
|
378
378
|
"build/dist/src/koffi/package.json"(exports2, module2) {
|
|
379
379
|
module2.exports = {
|
|
380
380
|
name: "koffi",
|
|
381
|
-
version: "2.
|
|
382
|
-
stable: "2.
|
|
381
|
+
version: "2.6.0",
|
|
382
|
+
stable: "2.6.0",
|
|
383
383
|
description: "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
384
384
|
keywords: [
|
|
385
385
|
"foreign",
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -1644,6 +1644,18 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
|
|
|
1644
1644
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for filename, expected string or null", GetValueType(instance, info[0]));
|
|
1645
1645
|
return env.Null();
|
|
1646
1646
|
}
|
|
1647
|
+
if (info.Length() >= 2 && !IsObject(info[1])) {
|
|
1648
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for options, expected object", GetValueType(instance, info[1]));
|
|
1649
|
+
return env.Null();
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
#ifndef _WIN32
|
|
1653
|
+
bool lazy = false;
|
|
1654
|
+
if (info.Length() >= 2) {
|
|
1655
|
+
Napi::Object options = info[1].As<Napi::Object>();
|
|
1656
|
+
lazy = options.Get("lazy").ToBoolean();
|
|
1657
|
+
}
|
|
1658
|
+
#endif
|
|
1647
1659
|
|
|
1648
1660
|
if (!instance->memories.len) {
|
|
1649
1661
|
AllocateMemory(instance, instance->config.sync_stack_size, instance->config.sync_heap_size);
|
|
@@ -1665,8 +1677,10 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
|
|
|
1665
1677
|
}
|
|
1666
1678
|
#else
|
|
1667
1679
|
if (info[0].IsString()) {
|
|
1680
|
+
int flags = lazy ? RTLD_LAZY : RTLD_NOW;
|
|
1681
|
+
|
|
1668
1682
|
std::string filename = info[0].As<Napi::String>();
|
|
1669
|
-
module = dlopen(filename.c_str(),
|
|
1683
|
+
module = dlopen(filename.c_str(), flags);
|
|
1670
1684
|
|
|
1671
1685
|
if (!module) {
|
|
1672
1686
|
const char *msg = dlerror();
|