koffi 3.0.0-alpha.7 → 3.0.0-alpha.8
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 +30 -0
- package/bin/koffi/darwin_arm64/koffi.node +0 -0
- package/bin/koffi/darwin_x64/koffi.node +0 -0
- package/bin/koffi/freebsd_arm64/koffi.node +0 -0
- package/bin/koffi/freebsd_ia32/koffi.node +0 -0
- package/bin/koffi/freebsd_x64/koffi.node +0 -0
- package/bin/koffi/linux_arm64/koffi.node +0 -0
- package/bin/koffi/linux_ia32/koffi.node +0 -0
- package/bin/koffi/linux_x64/koffi.node +0 -0
- package/bin/koffi/musl_arm64/koffi.node +0 -0
- package/bin/koffi/musl_x64/koffi.node +0 -0
- package/bin/koffi/openbsd_ia32/koffi.node +0 -0
- package/bin/koffi/openbsd_x64/koffi.node +0 -0
- package/bin/koffi/win32_ia32/koffi.node +0 -0
- package/bin/koffi/win32_x64/koffi.node +0 -0
- package/doc/callbacks.md +1 -1
- package/doc/contribute.md +1 -1
- package/doc/input.md +64 -0
- package/doc/misc.md +12 -13
- package/doc/pointers.md +2 -4
- package/doc/variables.md +4 -4
- package/index.d.ts +57 -53
- package/lib/native/base/base.hh +8 -1
- package/package.json +1 -1
- package/src/koffi/CMakeLists.txt +2 -2
- package/src/koffi/index.cjs +17 -4
- package/src/koffi/index.js +17 -4
- package/src/koffi/indirect.cjs +17 -4
- package/src/koffi/indirect.js +17 -4
- package/src/koffi/src/abi/arm64.cc +2 -0
- package/src/koffi/src/ffi.cc +181 -163
- package/src/koffi/src/ffi.hh +3 -3
- package/src/koffi/src/{trampolines.js → trampolines.cjs} +1 -1
- package/src/koffi/src/util.cc +160 -44
- package/src/koffi/src/util.hh +17 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,36 @@
|
|
|
3
3
|
> [!NOTE]
|
|
4
4
|
> Consult the [migration guide](migration) to migrate between major Koffi versions.
|
|
5
5
|
|
|
6
|
+
## Koffi 3
|
|
7
|
+
|
|
8
|
+
### Koffi 3.0
|
|
9
|
+
|
|
10
|
+
#### Koffi 3.0.0 (WIP)
|
|
11
|
+
|
|
12
|
+
**Main changes:**
|
|
13
|
+
|
|
14
|
+
- Replace use of externals with type objects:
|
|
15
|
+
* Use `koffi.type()` to resolve type specifiers (strings or objects) to type objects
|
|
16
|
+
* Access type information directly on type variables without `koffi.introspect()`
|
|
17
|
+
- Replace use of externals with BigInt pointers
|
|
18
|
+
- Rewrite call preparation and execution for vastly improved performance
|
|
19
|
+
|
|
20
|
+
**Other changes:**
|
|
21
|
+
|
|
22
|
+
- Add `koffi.enumeration()` to create [enum types](input#enum-types)
|
|
23
|
+
|
|
24
|
+
**Newly deprecated functions:**
|
|
25
|
+
|
|
26
|
+
- Deprecate `koffi.resolve()` function, replace with `koffi.type()`
|
|
27
|
+
- Deprecate `koffi.introspect()` function, replace with `koffi.type()`
|
|
28
|
+
|
|
29
|
+
**Removed deprecated functions:**
|
|
30
|
+
|
|
31
|
+
- Remove `koffi.callback()` long replaced with `koffi.proto()`
|
|
32
|
+
- Remove `koffi.handle()` long replaced with `koffi.opaque()`
|
|
33
|
+
|
|
34
|
+
Consult the [migration guide](migration) for more information.
|
|
35
|
+
|
|
6
36
|
## Koffi 2
|
|
7
37
|
|
|
8
38
|
### Koffi 2.16
|
|
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
|
@@ -162,7 +162,7 @@ let cb2 = koffi.register(store, store.get, 'IntCallback *'); // However in this
|
|
|
162
162
|
|
|
163
163
|
*New in Koffi 2.2, changed in Koffi 2.3*
|
|
164
164
|
|
|
165
|
-
Koffi does not have enough information to convert callback pointer arguments to an appropriate JS value. In this case, your JS function will receive
|
|
165
|
+
Koffi does not have enough information to convert callback pointer arguments to an appropriate JS value. In this case, your JS function will receive a *BigInt* value with the pointer address.
|
|
166
166
|
|
|
167
167
|
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#decode-to-js-values) function to decode pointer arguments.
|
|
168
168
|
|
package/doc/contribute.md
CHANGED
|
@@ -151,7 +151,7 @@ cd ../../bin/koffi/packages
|
|
|
151
151
|
./publish.sh
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
-
Some platforms are emulated so this can take a few minutes until the pre-built binaries are ready.
|
|
154
|
+
Some platforms are emulated so this can take a few minutes until the pre-built binaries are ready. You might want to go grab a cup of coffee :)
|
|
155
155
|
|
|
156
156
|
# Code style
|
|
157
157
|
|
package/doc/input.md
CHANGED
|
@@ -466,6 +466,70 @@ console.log(array); // Prints { count: 8, numbers: [1, 2, 3, 4, 5, 10, 12, 14] }
|
|
|
466
466
|
|
|
467
467
|
In C, dynamically-sized arrays are usually passed around as pointers. Read more about [array pointers](pointers#dynamic-arrays) in the relevant section.
|
|
468
468
|
|
|
469
|
+
# Enum types
|
|
470
|
+
|
|
471
|
+
*Added in Koffi 3.0*
|
|
472
|
+
|
|
473
|
+
C enumeration values are stored as integers. The underlying integer type is implementation-defined but Koffi tries to match usual platform behavior.
|
|
474
|
+
|
|
475
|
+
On POSIX platforms, Koffi follows the following rules:
|
|
476
|
+
|
|
477
|
+
- If no negative value exists: `unsigned int` by default, `uint64_t` if needed
|
|
478
|
+
- If any negative value exists: `int` by default, `int64_t` if needed
|
|
479
|
+
|
|
480
|
+
On Windows, things are simpler, and `int` is used all the time. Koffi will throw an error if any enumeration value does not fit in a 32-bit integer.
|
|
481
|
+
|
|
482
|
+
```js
|
|
483
|
+
// For OpenResult, the underlying type will be unsigned int on POSIX, int on Windows
|
|
484
|
+
const OpenResult = koffi.enumeration('OpenResult', {
|
|
485
|
+
Success: 0,
|
|
486
|
+
MissingFile: 1,
|
|
487
|
+
AccessDenied: 2,
|
|
488
|
+
OtherError: 3
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// For RelativePosition, the underlying type will be int everywhere
|
|
492
|
+
const RelativePosition = koffi.enumeration('RelativePosition', {
|
|
493
|
+
Left: -1,
|
|
494
|
+
Center: 0,
|
|
495
|
+
Right: 1
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// For IntLimits, the underlying type will be int64_t on POSIX, and fail on Windows
|
|
499
|
+
const Int64Limits = koffi.enumeration('Int64Limits', {
|
|
500
|
+
Min: -9223372036854775808n,
|
|
501
|
+
Max: 9223372036854775807n
|
|
502
|
+
});
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
```{warning}
|
|
506
|
+
This behavior may not match your compiler:
|
|
507
|
+
|
|
508
|
+
- POSIX platforms: GCC and Clang support will use a short integer type if `-fshort-enums` is specified and the enumeration values fit in `short` or `unsigned short`
|
|
509
|
+
- Windows: MSVC (and Clang) always use `int` even if some values do not fit, which matches what Koffi does... unless the compiler flag `/Zc:enumTypes` is set, maybe.
|
|
510
|
+
|
|
511
|
+
Use an explicit type specifier to work around these problems, as shown below.
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
You can access the constants in `values` member of the type object.
|
|
515
|
+
|
|
516
|
+
```js
|
|
517
|
+
console.log(OpenResult.values.MissingFile); // Prints 1
|
|
518
|
+
console.log(RelativePosition.values.Left); // Prints -1
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
You can specify the storage type explicitly as the last argument to `koffi.enumeration(name, values, type)`.
|
|
522
|
+
|
|
523
|
+
```js
|
|
524
|
+
// This one explictly uses int64_t as the underlying type,
|
|
525
|
+
// despite the fact that the values fit inside an int.
|
|
526
|
+
const ExplicitEnum = koffi.enumeration('ExplicitEnum', {
|
|
527
|
+
Zero: 0,
|
|
528
|
+
One: 1,
|
|
529
|
+
Two: 2
|
|
530
|
+
}, 'int64_t');
|
|
531
|
+
```
|
|
532
|
+
|
|
469
533
|
# Union types
|
|
470
534
|
|
|
471
535
|
The declaration and use of [union types](unions) will be explained in a later section, they are only briefly mentioned here if you need them.
|
package/doc/misc.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# Types
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Type specifiers
|
|
4
4
|
|
|
5
|
-
*
|
|
5
|
+
*Changed in Koffi 3.0*
|
|
6
6
|
|
|
7
7
|
> [!NOTE]
|
|
8
|
-
>
|
|
9
|
-
>
|
|
10
|
-
> In Koffi 1.x, it could only be used with struct types and returned the object passed to koffi.struct() with the member names and types.
|
|
11
|
-
>
|
|
12
|
-
> Starting in Koffi 2.2, each record member is exposed as an object containing the name, the type and the offset within the record.
|
|
8
|
+
> In Koffi 2.0, types were External values, you had to use `koffi.introspect()` to get type information. In Koffi 3.0, this information is directly available in type objects, and this function is deprecated.
|
|
13
9
|
>
|
|
14
10
|
> Consult the [migration guide](migration) for more information.
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
You can use strings or type objects to give type information to Koffi (when declaring functions, structs, and so on). Use `koffi.type(spec)` to resolve all accepted type values (strings and type objects) to type objects.
|
|
13
|
+
|
|
14
|
+
You can inspect the type object for information: name, primitive, size, alignment, members (record types), reference type (array, pointer), length (array), arguments and return type (prototypes).
|
|
17
15
|
|
|
18
16
|
```js
|
|
19
17
|
const FoobarType = koffi.struct('FoobarType', {
|
|
@@ -22,7 +20,7 @@ const FoobarType = koffi.struct('FoobarType', {
|
|
|
22
20
|
c: 'double'
|
|
23
21
|
});
|
|
24
22
|
|
|
25
|
-
console.log(
|
|
23
|
+
console.log(FoobarType);
|
|
26
24
|
|
|
27
25
|
// Expected result on 64-bit machines:
|
|
28
26
|
// {
|
|
@@ -30,10 +28,11 @@ console.log(koffi.introspect(FoobarType));
|
|
|
30
28
|
// primitive: 'Record',
|
|
31
29
|
// size: 24,
|
|
32
30
|
// alignment: 8,
|
|
31
|
+
// disposable: false,
|
|
33
32
|
// members: {
|
|
34
|
-
// a: { name: 'a', type: [
|
|
35
|
-
// b: { name: 'b', type: [
|
|
36
|
-
// c: { name: 'c', type: [
|
|
33
|
+
// a: { name: 'a', type: [Type], offset: 0 },
|
|
34
|
+
// b: { name: 'b', type: [Type], offset: 8 },
|
|
35
|
+
// c: { name: 'c', type: [Type], offset: 16 }
|
|
37
36
|
// }
|
|
38
37
|
// }
|
|
39
38
|
```
|
|
@@ -43,7 +42,7 @@ Koffi also exposes a few more utility functions to get a subset of this informat
|
|
|
43
42
|
- `koffi.sizeof(type)` to get the size of a type
|
|
44
43
|
- `koffi.alignof(type)` to get the alignment of a type
|
|
45
44
|
- `koffi.offsetof(type, member_name)` to get the offset of a record member
|
|
46
|
-
- `koffi.
|
|
45
|
+
- `koffi.type(type)` to get the resolved type object from a type string
|
|
47
46
|
|
|
48
47
|
Just like before, you can refer to primitive types by their name or through `koffi.types`:
|
|
49
48
|
|
package/doc/pointers.md
CHANGED
|
@@ -49,6 +49,8 @@ const GetHandleInformation = lib.func('bool __stdcall GetHandleInformation(HANDL
|
|
|
49
49
|
const CloseHandle = lib.func('bool __stdcall CloseHandle(HANDLE h)');
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
Koffi uses BigInt numbers to represent opaque pointers.
|
|
53
|
+
|
|
52
54
|
## Pointer to primitive types
|
|
53
55
|
|
|
54
56
|
In javascript, it is not possible to pass a primitive value by reference to another function. This means that you cannot call a function and expect it to modify the value of one of its number or string parameter.
|
|
@@ -322,7 +324,3 @@ function write(filename, str) {
|
|
|
322
324
|
}
|
|
323
325
|
}
|
|
324
326
|
```
|
|
325
|
-
|
|
326
|
-
# Unwrap pointers
|
|
327
|
-
|
|
328
|
-
You can use `koffi.address(ptr)` on a pointer to get the numeric value as a [BigInt object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
|
package/doc/variables.md
CHANGED
|
@@ -23,7 +23,7 @@ You cannot directly manipulate these variables, use:
|
|
|
23
23
|
|
|
24
24
|
*New in Koffi 2.2, changed in Koffi 2.3*
|
|
25
25
|
|
|
26
|
-
Use `koffi.decode()` to decode C pointers,
|
|
26
|
+
Use `koffi.decode()` to decode C pointers, represented by BigInt numbers.
|
|
27
27
|
|
|
28
28
|
Some arguments are optional and this function can be called in several ways:
|
|
29
29
|
|
|
@@ -66,12 +66,12 @@ console.log(koffi.decode(my_string, 'const char *', 3)) // Prints "foo"
|
|
|
66
66
|
|
|
67
67
|
*New in Koffi 2.6*
|
|
68
68
|
|
|
69
|
-
Use `koffi.encode()` to encode JS values into C symbols or pointers,
|
|
69
|
+
Use `koffi.encode()` to encode JS values into C symbols or pointers, which are represented by BigInt numbers.
|
|
70
70
|
|
|
71
71
|
Some arguments are optional and this function can be called in several ways:
|
|
72
72
|
|
|
73
|
-
- `koffi.encode(
|
|
74
|
-
- `koffi.encode(
|
|
73
|
+
- `koffi.encode(ptr, type, value)`: no offset
|
|
74
|
+
- `koffi.encode(ptr, offset, type, value)`: explicit offset to add to the pointer before encoding
|
|
75
75
|
|
|
76
76
|
We'll reuse the examples shown above and change the variable values with `koffi.encode()`.
|
|
77
77
|
|
package/index.d.ts
CHANGED
|
@@ -19,8 +19,12 @@ type PrimitiveKind = 'Void' | 'Bool' | 'Int8' | 'UInt8' | 'Int16' | 'Int16S' | '
|
|
|
19
19
|
'Prototype' | 'Callback';
|
|
20
20
|
type ArrayHint = 'Array' | 'Typed' | 'String';
|
|
21
21
|
|
|
22
|
-
type
|
|
23
|
-
|
|
22
|
+
type PrototypeInfo = {
|
|
23
|
+
name: string;
|
|
24
|
+
arguments: TypeInfo[];
|
|
25
|
+
result: TypeInfo
|
|
26
|
+
};
|
|
27
|
+
|
|
24
28
|
type TypeInfo = {
|
|
25
29
|
name: string;
|
|
26
30
|
primitive: PrimitiveKind;
|
|
@@ -29,26 +33,22 @@ type TypeInfo = {
|
|
|
29
33
|
disposable: boolean;
|
|
30
34
|
length?: number;
|
|
31
35
|
hint?: ArrayHint;
|
|
32
|
-
ref?:
|
|
33
|
-
members?: Record<string, { name: string, type:
|
|
36
|
+
ref?: TypeInfo;
|
|
37
|
+
members?: Record<string, { name: string, type: TypeInfo, offset: number }>;
|
|
38
|
+
proto?: PrototypeInfo;
|
|
39
|
+
values?: Record<string, number | bigint>;
|
|
34
40
|
};
|
|
41
|
+
type TypeSpec = string | TypeInfo | IKoffiCType;
|
|
42
|
+
type TypeSpecWithAlignment = TypeSpec | [number, TypeSpec];
|
|
43
|
+
|
|
35
44
|
type KoffiFunction = {
|
|
36
45
|
(...args: any[]) : any;
|
|
37
46
|
async: (...args: any[]) => any;
|
|
38
|
-
info:
|
|
39
|
-
name: string,
|
|
40
|
-
arguments: IKoffiCType[],
|
|
41
|
-
result: IKoffiCType
|
|
42
|
-
};
|
|
47
|
+
info: PrototypeInfo;
|
|
43
48
|
};
|
|
44
|
-
|
|
45
49
|
export type KoffiFunc<T extends (...args: any) => any> = T & {
|
|
46
50
|
async: (...args: [...Parameters<T>, (err: any, result: ReturnType<T>) => void]) => void;
|
|
47
|
-
info:
|
|
48
|
-
name: string;
|
|
49
|
-
arguments: IKoffiCType[];
|
|
50
|
-
result: IKoffiCType;
|
|
51
|
-
};
|
|
51
|
+
info: PrototypeInfo;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
export interface IKoffiLib {
|
|
@@ -70,53 +70,56 @@ export interface IKoffiLib {
|
|
|
70
70
|
unload(): void;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export function struct(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>):
|
|
74
|
-
export function struct(ref:
|
|
75
|
-
export function struct(def: Record<string, TypeSpecWithAlignment>):
|
|
76
|
-
export function pack(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>):
|
|
77
|
-
export function pack(ref:
|
|
78
|
-
export function pack(def: Record<string, TypeSpecWithAlignment>):
|
|
73
|
+
export function struct(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
74
|
+
export function struct(ref: TypeInfo, def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
75
|
+
export function struct(def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
76
|
+
export function pack(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
77
|
+
export function pack(ref: TypeInfo, def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
78
|
+
export function pack(def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
79
79
|
|
|
80
|
-
export function union(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>):
|
|
81
|
-
export function union(ref:
|
|
82
|
-
export function union(def: Record<string, TypeSpecWithAlignment>):
|
|
80
|
+
export function union(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
81
|
+
export function union(ref: TypeInfo, def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
82
|
+
export function union(def: Record<string, TypeSpecWithAlignment>): TypeInfo;
|
|
83
83
|
|
|
84
84
|
export class Union {
|
|
85
85
|
constructor(type: TypeSpec);
|
|
86
86
|
[s: string]: any;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
export function
|
|
90
|
-
export function
|
|
89
|
+
export function enumeration(name: string | null | undefined, def: Record<string, number | bigint>, storage?: TypeSpec | null) : TypeInfo;
|
|
90
|
+
export function enumeration(def: Record<string, number | bigint>, storage?: TypeSpec | null) : TypeInfo;
|
|
91
|
+
|
|
92
|
+
export function array(ref: TypeSpec, len: number, hint?: ArrayHint | null): TypeInfo;
|
|
93
|
+
export function array(ref: TypeSpec, countedBy: string, maxLen: number, hint?: ArrayHint | null): TypeInfo;
|
|
91
94
|
|
|
92
|
-
export function opaque(name: string | null | undefined):
|
|
93
|
-
export function opaque():
|
|
94
|
-
/** @deprecated */ export function handle(name: string | null | undefined):
|
|
95
|
-
/** @deprecated */ export function handle():
|
|
95
|
+
export function opaque(name: string | null | undefined): TypeInfo;
|
|
96
|
+
export function opaque(): TypeInfo;
|
|
97
|
+
/** @deprecated */ export function handle(name: string | null | undefined): TypeInfo;
|
|
98
|
+
/** @deprecated */ export function handle(): TypeInfo;
|
|
96
99
|
|
|
97
|
-
export function pointer(ref: TypeSpec):
|
|
98
|
-
export function pointer(ref: TypeSpec, count: number):
|
|
99
|
-
export function pointer(name: string | null | undefined, ref: TypeSpec, countedBy?: string | null):
|
|
100
|
-
export function pointer(name: string | null | undefined, ref: TypeSpec, count: number):
|
|
100
|
+
export function pointer(ref: TypeSpec): TypeInfo;
|
|
101
|
+
export function pointer(ref: TypeSpec, count: number): TypeInfo;
|
|
102
|
+
export function pointer(name: string | null | undefined, ref: TypeSpec, countedBy?: string | null): TypeInfo;
|
|
103
|
+
export function pointer(name: string | null | undefined, ref: TypeSpec, count: number): TypeInfo;
|
|
101
104
|
|
|
102
105
|
export function out(type: TypeSpec): IKoffiCType;
|
|
103
106
|
export function inout(type: TypeSpec): IKoffiCType;
|
|
104
107
|
|
|
105
|
-
export function disposable(type: TypeSpec):
|
|
106
|
-
export function disposable(type: TypeSpec, freeFunction: Function):
|
|
107
|
-
export function disposable(name: string | null | undefined, type: TypeSpec):
|
|
108
|
-
export function disposable(name: string | null | undefined, type: TypeSpec, freeFunction: Function):
|
|
109
|
-
|
|
110
|
-
export function proto(definition: string):
|
|
111
|
-
export function proto(result: TypeSpec, arguments: TypeSpec[]):
|
|
112
|
-
export function proto(convention: string, result: TypeSpec, arguments: TypeSpec[]):
|
|
113
|
-
export function proto(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]):
|
|
114
|
-
export function proto(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]):
|
|
115
|
-
/** @deprecated */ export function callback(definition: string):
|
|
116
|
-
/** @deprecated */ export function callback(result: TypeSpec, arguments: TypeSpec[]):
|
|
117
|
-
/** @deprecated */ export function callback(convention: string, result: TypeSpec, arguments: TypeSpec[]):
|
|
118
|
-
/** @deprecated */ export function callback(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]):
|
|
119
|
-
/** @deprecated */ export function callback(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]):
|
|
108
|
+
export function disposable(type: TypeSpec): TypeInfo;
|
|
109
|
+
export function disposable(type: TypeSpec, freeFunction: Function): TypeInfo;
|
|
110
|
+
export function disposable(name: string | null | undefined, type: TypeSpec): TypeInfo;
|
|
111
|
+
export function disposable(name: string | null | undefined, type: TypeSpec, freeFunction: Function): TypeInfo;
|
|
112
|
+
|
|
113
|
+
export function proto(definition: string): TypeInfo;
|
|
114
|
+
export function proto(result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
115
|
+
export function proto(convention: string, result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
116
|
+
export function proto(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
117
|
+
export function proto(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
118
|
+
/** @deprecated */ export function callback(definition: string): TypeInfo;
|
|
119
|
+
/** @deprecated */ export function callback(result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
120
|
+
/** @deprecated */ export function callback(convention: string, result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
121
|
+
/** @deprecated */ export function callback(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
122
|
+
/** @deprecated */ export function callback(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): TypeInfo;
|
|
120
123
|
|
|
121
124
|
export function register(callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
|
122
125
|
export function register(thisValue: any, callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
|
@@ -136,13 +139,14 @@ export function encode(ref: any, offset: number, type: TypeSpec, value: any): vo
|
|
|
136
139
|
export function encode(ref: any, offset: number, type: TypeSpec, value: any, len: number): void;
|
|
137
140
|
export function view(ref: any, len: number): ArrayBuffer;
|
|
138
141
|
|
|
142
|
+
export function type(type: TypeSpec): TypeInfo;
|
|
139
143
|
export function sizeof(type: TypeSpec): number;
|
|
140
144
|
export function alignof(type: TypeSpec): number;
|
|
141
145
|
export function offsetof(type: TypeSpec, member_name: string): number;
|
|
142
|
-
export function resolve(type: TypeSpec):
|
|
143
|
-
export function introspect(type: TypeSpec): TypeInfo;
|
|
146
|
+
/** @deprecated */ export function resolve(type: TypeSpec): TypeInfo;
|
|
147
|
+
/** @deprecated */ export function introspect(type: TypeSpec): TypeInfo;
|
|
144
148
|
|
|
145
|
-
export function alias(name: string, type: TypeSpec):
|
|
149
|
+
export function alias(name: string, type: TypeSpec): TypeInfo;
|
|
146
150
|
|
|
147
151
|
type KoffiConfig = {
|
|
148
152
|
sync_stack_size?: number;
|
|
@@ -257,7 +261,7 @@ type PrimitiveTypes =
|
|
|
257
261
|
| 'void'
|
|
258
262
|
| 'wchar'
|
|
259
263
|
| 'wchar_t';
|
|
260
|
-
export const types: Record<PrimitiveTypes,
|
|
264
|
+
export const types: Record<PrimitiveTypes, TypeInfo>;
|
|
261
265
|
|
|
262
266
|
export interface IKoffiPollOptions {
|
|
263
267
|
readable?: boolean;
|
package/lib/native/base/base.hh
CHANGED
|
@@ -3645,7 +3645,14 @@ static inline int64_t GetCoreCycles()
|
|
|
3645
3645
|
{
|
|
3646
3646
|
uint64_t counter;
|
|
3647
3647
|
__asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (counter));
|
|
3648
|
-
return counter;
|
|
3648
|
+
return (int64_t)counter;
|
|
3649
|
+
}
|
|
3650
|
+
#elif defined(__riscv)
|
|
3651
|
+
static inline int64_t GetCoreCycles()
|
|
3652
|
+
{
|
|
3653
|
+
uint64_t counter;
|
|
3654
|
+
__asm__ __volatile__("csrr %0, mcycle" : "=r"(counter));
|
|
3655
|
+
return (int64_t)counter;
|
|
3649
3656
|
}
|
|
3650
3657
|
#endif
|
|
3651
3658
|
|
package/package.json
CHANGED
package/src/koffi/CMakeLists.txt
CHANGED
|
@@ -60,8 +60,8 @@ add_custom_command(OUTPUT trampolines/gnu.inc
|
|
|
60
60
|
trampolines/masm64.inc
|
|
61
61
|
COMMENT "Generate trampoline macros"
|
|
62
62
|
COMMAND "${NODE_JS_EXECPATH}"
|
|
63
|
-
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/src/trampolines.
|
|
64
|
-
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/trampolines.
|
|
63
|
+
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/src/trampolines.cjs" "${CMAKE_CURRENT_BINARY_DIR}/trampolines" 8192
|
|
64
|
+
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/trampolines.cjs")
|
|
65
65
|
|
|
66
66
|
set(KOFFI_SRC
|
|
67
67
|
src/call.cc
|
package/src/koffi/index.cjs
CHANGED
|
@@ -131,7 +131,7 @@ var init_abi = __esm({
|
|
|
131
131
|
var package_default;
|
|
132
132
|
var init_package = __esm({
|
|
133
133
|
"package.json"() {
|
|
134
|
-
package_default = { name: "koffi", version: "3.0.0-alpha.
|
|
134
|
+
package_default = { name: "koffi", version: "3.0.0-alpha.8", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
135
135
|
}
|
|
136
136
|
});
|
|
137
137
|
|
|
@@ -163,7 +163,7 @@ function loadDynamic(root, pkg2, triplets2) {
|
|
|
163
163
|
roots.push(process.resourcesPath + "/node_modules/koffi");
|
|
164
164
|
}
|
|
165
165
|
let names = [
|
|
166
|
-
|
|
166
|
+
`../../../@koromix/koffi-${pkg2}`,
|
|
167
167
|
...triplets2.flatMap((triplet) => roots.map((dir) => `${dir}/bin/koffi/${triplet}/koffi.node`))
|
|
168
168
|
];
|
|
169
169
|
for (let name of names) {
|
|
@@ -182,6 +182,19 @@ function loadDynamic(root, pkg2, triplets2) {
|
|
|
182
182
|
}
|
|
183
183
|
function wrapNative(native2) {
|
|
184
184
|
let load = native2.load;
|
|
185
|
+
native2.sizeof = (spec) => native2.type(spec).size;
|
|
186
|
+
native2.alignof = (spec) => native2.type(spec).alignment;
|
|
187
|
+
native2.offsetof = (spec, name) => {
|
|
188
|
+
let type = native2.type(spec);
|
|
189
|
+
if (type.primitive != "Record")
|
|
190
|
+
throw new TypeError("The offsetof() function can only be used with record types");
|
|
191
|
+
let member = type.members[name];
|
|
192
|
+
if (member == null)
|
|
193
|
+
throw new Error(`Record type ${type.name} does not have member '${name}'`);
|
|
194
|
+
return member.offset;
|
|
195
|
+
};
|
|
196
|
+
native2.resolve = import_util.default.deprecate(native2.type, "The koffi.resolve() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI007");
|
|
197
|
+
native2.introspect = import_util.default.deprecate(native2.type, "The koffi.introspect() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI008");
|
|
185
198
|
native2.load = (...args) => {
|
|
186
199
|
let lib = load(...args);
|
|
187
200
|
lib.cdecl = import_util.default.deprecate((...args2) => lib.func("__cdecl", ...args2), "The koffi.cdecl() function was deprecated in Koffi 2.7, use koffi.func(...) instead", "KOFFI003");
|
|
@@ -198,7 +211,7 @@ var init_init = __esm({
|
|
|
198
211
|
import_node_module = require("node:module");
|
|
199
212
|
init_abi();
|
|
200
213
|
init_package();
|
|
201
|
-
requireNative = (0, import_node_module.createRequire)(
|
|
214
|
+
requireNative = (0, import_node_module.createRequire)(__filename);
|
|
202
215
|
}
|
|
203
216
|
});
|
|
204
217
|
|
|
@@ -206,7 +219,7 @@ var init_init = __esm({
|
|
|
206
219
|
var require_static = __commonJS({
|
|
207
220
|
"src/static.js"(exports2, module2) {
|
|
208
221
|
var { createRequire: createRequire2 } = require("node:module");
|
|
209
|
-
var requireNative2 = createRequire2(
|
|
222
|
+
var requireNative2 = createRequire2(__filename);
|
|
210
223
|
function loadStatic2(pkg2) {
|
|
211
224
|
let native2 = null;
|
|
212
225
|
if (native2 == null && pkg2 == "linux-arm64") {
|
package/src/koffi/index.js
CHANGED
|
@@ -93,10 +93,10 @@ function decodeElfHeader(buf) {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// package.json
|
|
96
|
-
var package_default = { name: "koffi", version: "3.0.0-alpha.
|
|
96
|
+
var package_default = { name: "koffi", version: "3.0.0-alpha.8", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
97
97
|
|
|
98
98
|
// src/init.js
|
|
99
|
-
var requireNative = createRequire(import.meta.
|
|
99
|
+
var requireNative = createRequire(import.meta.url);
|
|
100
100
|
function detectPlatform() {
|
|
101
101
|
if (process.versions.napi == null || process.versions.napi < package_default.cnoke.napi) {
|
|
102
102
|
let major = parseInt(process.versions.node, 10);
|
|
@@ -118,7 +118,7 @@ function loadDynamic(root, pkg2, triplets2) {
|
|
|
118
118
|
roots.push(process.resourcesPath + "/node_modules/koffi");
|
|
119
119
|
}
|
|
120
120
|
let names = [
|
|
121
|
-
|
|
121
|
+
`../../../@koromix/koffi-${pkg2}`,
|
|
122
122
|
...triplets2.flatMap((triplet) => roots.map((dir) => `${dir}/bin/koffi/${triplet}/koffi.node`))
|
|
123
123
|
];
|
|
124
124
|
for (let name of names) {
|
|
@@ -137,6 +137,19 @@ function loadDynamic(root, pkg2, triplets2) {
|
|
|
137
137
|
}
|
|
138
138
|
function wrapNative(native2) {
|
|
139
139
|
let load = native2.load;
|
|
140
|
+
native2.sizeof = (spec) => native2.type(spec).size;
|
|
141
|
+
native2.alignof = (spec) => native2.type(spec).alignment;
|
|
142
|
+
native2.offsetof = (spec, name) => {
|
|
143
|
+
let type = native2.type(spec);
|
|
144
|
+
if (type.primitive != "Record")
|
|
145
|
+
throw new TypeError("The offsetof() function can only be used with record types");
|
|
146
|
+
let member = type.members[name];
|
|
147
|
+
if (member == null)
|
|
148
|
+
throw new Error(`Record type ${type.name} does not have member '${name}'`);
|
|
149
|
+
return member.offset;
|
|
150
|
+
};
|
|
151
|
+
native2.resolve = util.deprecate(native2.type, "The koffi.resolve() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI007");
|
|
152
|
+
native2.introspect = util.deprecate(native2.type, "The koffi.introspect() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI008");
|
|
140
153
|
native2.load = (...args) => {
|
|
141
154
|
let lib = load(...args);
|
|
142
155
|
lib.cdecl = util.deprecate((...args2) => lib.func("__cdecl", ...args2), "The koffi.cdecl() function was deprecated in Koffi 2.7, use koffi.func(...) instead", "KOFFI003");
|
|
@@ -149,7 +162,7 @@ function wrapNative(native2) {
|
|
|
149
162
|
|
|
150
163
|
// src/static.js
|
|
151
164
|
import { createRequire as createRequire2 } from "node:module";
|
|
152
|
-
var requireNative2 = createRequire2(import.meta.
|
|
165
|
+
var requireNative2 = createRequire2(import.meta.url);
|
|
153
166
|
function loadStatic(pkg2) {
|
|
154
167
|
let native2 = null;
|
|
155
168
|
if (native2 == null && pkg2 == "linux-arm64") {
|
package/src/koffi/indirect.cjs
CHANGED
|
@@ -131,7 +131,7 @@ var init_abi = __esm({
|
|
|
131
131
|
var package_default;
|
|
132
132
|
var init_package = __esm({
|
|
133
133
|
"package.json"() {
|
|
134
|
-
package_default = { name: "koffi", version: "3.0.0-alpha.
|
|
134
|
+
package_default = { name: "koffi", version: "3.0.0-alpha.8", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
135
135
|
}
|
|
136
136
|
});
|
|
137
137
|
|
|
@@ -163,7 +163,7 @@ function loadDynamic(root, pkg2, triplets2) {
|
|
|
163
163
|
roots.push(process.resourcesPath + "/node_modules/koffi");
|
|
164
164
|
}
|
|
165
165
|
let names = [
|
|
166
|
-
|
|
166
|
+
`../../../@koromix/koffi-${pkg2}`,
|
|
167
167
|
...triplets2.flatMap((triplet) => roots.map((dir) => `${dir}/bin/koffi/${triplet}/koffi.node`))
|
|
168
168
|
];
|
|
169
169
|
for (let name of names) {
|
|
@@ -182,6 +182,19 @@ function loadDynamic(root, pkg2, triplets2) {
|
|
|
182
182
|
}
|
|
183
183
|
function wrapNative(native2) {
|
|
184
184
|
let load = native2.load;
|
|
185
|
+
native2.sizeof = (spec) => native2.type(spec).size;
|
|
186
|
+
native2.alignof = (spec) => native2.type(spec).alignment;
|
|
187
|
+
native2.offsetof = (spec, name) => {
|
|
188
|
+
let type = native2.type(spec);
|
|
189
|
+
if (type.primitive != "Record")
|
|
190
|
+
throw new TypeError("The offsetof() function can only be used with record types");
|
|
191
|
+
let member = type.members[name];
|
|
192
|
+
if (member == null)
|
|
193
|
+
throw new Error(`Record type ${type.name} does not have member '${name}'`);
|
|
194
|
+
return member.offset;
|
|
195
|
+
};
|
|
196
|
+
native2.resolve = import_util.default.deprecate(native2.type, "The koffi.resolve() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI007");
|
|
197
|
+
native2.introspect = import_util.default.deprecate(native2.type, "The koffi.introspect() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI008");
|
|
185
198
|
native2.load = (...args) => {
|
|
186
199
|
let lib = load(...args);
|
|
187
200
|
lib.cdecl = import_util.default.deprecate((...args2) => lib.func("__cdecl", ...args2), "The koffi.cdecl() function was deprecated in Koffi 2.7, use koffi.func(...) instead", "KOFFI003");
|
|
@@ -198,7 +211,7 @@ var init_init = __esm({
|
|
|
198
211
|
import_node_module = require("node:module");
|
|
199
212
|
init_abi();
|
|
200
213
|
init_package();
|
|
201
|
-
requireNative = (0, import_node_module.createRequire)(
|
|
214
|
+
requireNative = (0, import_node_module.createRequire)(__filename);
|
|
202
215
|
}
|
|
203
216
|
});
|
|
204
217
|
|
|
@@ -206,7 +219,7 @@ var init_init = __esm({
|
|
|
206
219
|
var require_static = __commonJS({
|
|
207
220
|
"src/static.js"(exports2, module2) {
|
|
208
221
|
var { createRequire: createRequire2 } = require("node:module");
|
|
209
|
-
var requireNative2 = createRequire2(
|
|
222
|
+
var requireNative2 = createRequire2(__filename);
|
|
210
223
|
function loadStatic2(pkg2) {
|
|
211
224
|
let native2 = null;
|
|
212
225
|
if (native2 == null && pkg2 == "linux-arm64") {
|