node-ctypes 1.6.0 → 1.8.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/README.md +15 -3
- package/build/Release/ctypes-darwin-arm64.node +0 -0
- package/build/Release/ctypes-darwin-x64.node +0 -0
- package/build/Release/ctypes-linux-arm64.node +0 -0
- package/build/Release/ctypes-linux-x64.node +0 -0
- package/build/Release/ctypes-win32-arm64.node +0 -0
- package/build/Release/ctypes-win32-x64.node +0 -0
- package/lib/index.d.ts +210 -16
- package/lib/index.js +34 -1
- package/lib/memory/operations.js +19 -0
- package/lib/memory/pointer.js +69 -6
- package/lib/structures/helpers/struct.js +88 -0
- package/lib/structures/helpers/union.js +56 -0
- package/lib/types/primitives.js +16 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,13 +119,22 @@ const buf = Buffer.alloc(4);
|
|
|
119
119
|
buf.writeInt32LE(42, 0);
|
|
120
120
|
|
|
121
121
|
const p = IntPtr.fromBuffer(buf);
|
|
122
|
-
console.log(p.contents); // 42
|
|
123
|
-
console.log(p[0]);
|
|
122
|
+
console.log(p.contents); // 42 (like *p in C)
|
|
123
|
+
console.log(p[0]); // 42 (like p[0] in C)
|
|
124
124
|
|
|
125
125
|
// pointer() function
|
|
126
126
|
const x = new c_int32(42);
|
|
127
127
|
const px = pointer(x);
|
|
128
128
|
console.log(px.contents); // 42
|
|
129
|
+
|
|
130
|
+
// fromAddress() — typed access to native memory
|
|
131
|
+
const pValues = POINTER(MyStruct).fromAddress(nativeAddr);
|
|
132
|
+
console.log(pValues[0].field); // pointer arithmetic (like pValues[0] in C)
|
|
133
|
+
console.log(pValues[5].field); // pValues + 5 * sizeof(MyStruct)
|
|
134
|
+
|
|
135
|
+
// cast() to POINTER — Python: cast(c_void_p(addr), POINTER(MyStruct))
|
|
136
|
+
const pData = cast(rawAddr, POINTER(MyStruct));
|
|
137
|
+
console.log(pData[0].field); // same result as fromAddress()
|
|
129
138
|
```
|
|
130
139
|
|
|
131
140
|
### Callbacks
|
|
@@ -194,11 +203,12 @@ console.log(`${st.wYear}-${st.wMonth}-${st.wDay}`);
|
|
|
194
203
|
| Callbacks | `CFUNCTYPE(c_int, c_int)` | `CFUNCTYPE(c_int, c_int)` |
|
|
195
204
|
| Pointers | `POINTER(c_int)` / `pointer(obj)` | `POINTER(c_int)` / `pointer(obj)` |
|
|
196
205
|
| Sizeof | `sizeof(c_int)` | `sizeof(c_int)` |
|
|
206
|
+
| Alignment | `alignment(c_int)` | `alignment(c_int)` |
|
|
197
207
|
| Strings | `c_char_p(b"hello")` | `create_string_buffer("hello")` |
|
|
198
208
|
| Variadic | `sprintf(buf, b"%d", 42)` | `sprintf(buf, "%d", 42)` |
|
|
199
209
|
| Errno | `get_errno()` | `get_errno()` |
|
|
200
210
|
| byref | `byref(obj)` | `byref(obj)` |
|
|
201
|
-
| cast | `cast(ptr, type)` | `cast(ptr, type)` |
|
|
211
|
+
| cast | `cast(ptr, type)` | `cast(ptr, type)` (supports `POINTER()` target) |
|
|
202
212
|
|
|
203
213
|
## Supported Types
|
|
204
214
|
|
|
@@ -219,6 +229,7 @@ console.log(`${st.wYear}-${st.wMonth}-${st.wDay}`);
|
|
|
219
229
|
| `c_wchar_p` | wide string | pointer |
|
|
220
230
|
| `c_bool` | | 1 |
|
|
221
231
|
| `c_size_t` | | platform |
|
|
232
|
+
| `c_ssize_t` | | platform |
|
|
222
233
|
|
|
223
234
|
## Key Differences from Python ctypes
|
|
224
235
|
|
|
@@ -233,6 +244,7 @@ console.log(`${st.wYear}-${st.wMonth}-${st.wDay}`);
|
|
|
233
244
|
- `string_at(address, size)` / `wstring_at(address, size)` — read strings from memory
|
|
234
245
|
- `readValue(ptr, type, offset)` / `writeValue(ptr, type, value, offset)` — direct memory access
|
|
235
246
|
- `sizeof(type)` — type size in bytes
|
|
247
|
+
- `alignment(type)` — type alignment in bytes
|
|
236
248
|
- `addressof(ptr)` — get address as BigInt
|
|
237
249
|
- `memmove(dst, src, count)` / `memset(dst, value, count)` — memory operations
|
|
238
250
|
- `GetLastError()` / `FormatError(code)` — Windows error helpers
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/index.d.ts
CHANGED
|
@@ -373,7 +373,7 @@ export class ThreadSafeCallback extends Callback {}
|
|
|
373
373
|
*/
|
|
374
374
|
export interface FieldDef {
|
|
375
375
|
name: string;
|
|
376
|
-
type: AnyType | StructDef | ArrayTypeDef | BitFieldDef;
|
|
376
|
+
type: AnyType | StructDef | ArrayTypeDef | BitFieldDef | PointerTypeDef;
|
|
377
377
|
offset: number;
|
|
378
378
|
size: number;
|
|
379
379
|
alignment: number;
|
|
@@ -419,7 +419,7 @@ export interface StructDef {
|
|
|
419
419
|
}
|
|
420
420
|
|
|
421
421
|
/** @category Structures */
|
|
422
|
-
export type FieldSpec = AnyType | StructDef | ArrayTypeDef | BitFieldDef | AnonymousField;
|
|
422
|
+
export type FieldSpec = AnyType | StructDef | ArrayTypeDef | BitFieldDef | AnonymousField | PointerTypeDef;
|
|
423
423
|
|
|
424
424
|
type JsFromCType<T> = T extends "int64" | "uint64" | "size_t"
|
|
425
425
|
? bigint
|
|
@@ -544,14 +544,109 @@ export interface AnonymousField {
|
|
|
544
544
|
// Pointers
|
|
545
545
|
// =============================================================================
|
|
546
546
|
|
|
547
|
+
/**
|
|
548
|
+
* A pointer instance created by {@link PointerTypeDef.create}, {@link PointerTypeDef.fromBuffer},
|
|
549
|
+
* or {@link PointerTypeDef.fromAddress}.
|
|
550
|
+
*
|
|
551
|
+
* Supports Python ctypes-compatible `.contents` property and C-like `[index]` pointer arithmetic.
|
|
552
|
+
*
|
|
553
|
+
* @example
|
|
554
|
+
* ```javascript
|
|
555
|
+
* const IntPtr = POINTER(c_int32);
|
|
556
|
+
* const p = IntPtr.fromBuffer(buf);
|
|
557
|
+
* console.log(p.contents); // dereferenced value (like *p in C)
|
|
558
|
+
* console.log(p[0]); // same as p.contents
|
|
559
|
+
* console.log(p[5]); // pointer arithmetic (like p[5] in C)
|
|
560
|
+
* ```
|
|
561
|
+
*
|
|
562
|
+
* @example Access a native array via pointer from a struct field
|
|
563
|
+
* ```javascript
|
|
564
|
+
* // When a struct has a c_void_p field pointing to an array of structs:
|
|
565
|
+
* const pValues = POINTER(ADSVALUE).fromAddress(col.pADsValues);
|
|
566
|
+
* for (let i = 0; i < col.dwNumValues; i++) {
|
|
567
|
+
* console.log(pValues[i].dwType); // struct view at pValues + i * sizeof(ADSVALUE)
|
|
568
|
+
* }
|
|
569
|
+
* ```
|
|
570
|
+
*
|
|
571
|
+
* @category Pointers
|
|
572
|
+
*/
|
|
573
|
+
export interface PointerInstance {
|
|
574
|
+
/** The pointer type definition this instance was created from. */
|
|
575
|
+
readonly _pointerType: PointerTypeDef;
|
|
576
|
+
/** The base type this pointer points to. */
|
|
577
|
+
readonly _baseType: AnyType | StructDef;
|
|
578
|
+
/** Size of the pointed-to type in bytes. */
|
|
579
|
+
readonly _baseSize: number;
|
|
580
|
+
|
|
581
|
+
/** Raw memory address as BigInt. */
|
|
582
|
+
readonly address: bigint;
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Dereference the pointer — read/write the value at the pointed location.
|
|
586
|
+
*
|
|
587
|
+
* Python equivalent: `p.contents`
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```javascript
|
|
591
|
+
* const p = POINTER(c_int32).fromBuffer(buf);
|
|
592
|
+
* console.log(p.contents); // read value
|
|
593
|
+
* p.contents = 42; // write value
|
|
594
|
+
* ```
|
|
595
|
+
*/
|
|
596
|
+
contents: any;
|
|
597
|
+
|
|
598
|
+
/** The underlying buffer (if created from a buffer), or null. */
|
|
599
|
+
readonly _buffer: Buffer | null;
|
|
600
|
+
|
|
601
|
+
/** Alias for contents getter. */
|
|
602
|
+
deref(): any;
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Set pointer to a new target (buffer or address).
|
|
606
|
+
* @param value - Buffer to point to, or BigInt/number address
|
|
607
|
+
*/
|
|
608
|
+
set(value: Buffer | bigint | number): void;
|
|
609
|
+
|
|
610
|
+
/** Check if this is a NULL pointer. */
|
|
611
|
+
readonly isNull: boolean;
|
|
612
|
+
|
|
613
|
+
/** Get pointer as an 8-byte buffer containing the address. */
|
|
614
|
+
toBuffer(): Buffer;
|
|
615
|
+
|
|
616
|
+
toString(): string;
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Pointer arithmetic — access elements at offset from the pointer.
|
|
620
|
+
*
|
|
621
|
+
* `p[i]` reads `sizeof(baseType)` bytes at `address + i * sizeof(baseType)`,
|
|
622
|
+
* exactly like C pointer indexing.
|
|
623
|
+
*
|
|
624
|
+
* @example
|
|
625
|
+
* ```javascript
|
|
626
|
+
* const arr = POINTER(c_int32).fromAddress(arrayAddr);
|
|
627
|
+
* arr[0] // first element
|
|
628
|
+
* arr[5] // sixth element
|
|
629
|
+
* arr[2] = 99; // write to third element
|
|
630
|
+
* ```
|
|
631
|
+
*/
|
|
632
|
+
[index: number]: any;
|
|
633
|
+
}
|
|
634
|
+
|
|
547
635
|
/**
|
|
548
636
|
* A pointer type created by {@link POINTER}.
|
|
549
637
|
*
|
|
550
638
|
* @example
|
|
551
639
|
* ```javascript
|
|
552
640
|
* const IntPtr = POINTER(c_int32);
|
|
641
|
+
*
|
|
642
|
+
* // From existing buffer
|
|
553
643
|
* const p = IntPtr.fromBuffer(buf);
|
|
554
|
-
* console.log(p.contents); //
|
|
644
|
+
* console.log(p.contents); // 42
|
|
645
|
+
* console.log(p[0]); // 42
|
|
646
|
+
*
|
|
647
|
+
* // From raw address (e.g., from a struct's c_void_p field)
|
|
648
|
+
* const pValues = POINTER(MyStruct).fromAddress(someStruct.pData);
|
|
649
|
+
* console.log(pValues[0].field1);
|
|
555
650
|
* ```
|
|
556
651
|
*
|
|
557
652
|
* @category Pointers
|
|
@@ -564,14 +659,63 @@ export interface PointerTypeDef {
|
|
|
564
659
|
/** Pointer size (always 8 on 64-bit). */
|
|
565
660
|
readonly size: number;
|
|
566
661
|
|
|
567
|
-
/**
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
662
|
+
/**
|
|
663
|
+
* Create a NULL pointer instance.
|
|
664
|
+
*
|
|
665
|
+
* @example
|
|
666
|
+
* ```javascript
|
|
667
|
+
* const p = POINTER(c_int32).create();
|
|
668
|
+
* console.log(p.isNull); // true
|
|
669
|
+
* ```
|
|
670
|
+
*/
|
|
671
|
+
create(value?: Buffer | bigint | number): PointerInstance;
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Create a pointer from an existing buffer (points to that buffer's memory).
|
|
675
|
+
*
|
|
676
|
+
* @param targetBuf - Buffer to point to
|
|
677
|
+
*
|
|
678
|
+
* @example
|
|
679
|
+
* ```javascript
|
|
680
|
+
* const buf = Buffer.alloc(4);
|
|
681
|
+
* buf.writeInt32LE(42, 0);
|
|
682
|
+
* const p = POINTER(c_int32).fromBuffer(buf);
|
|
683
|
+
* console.log(p.contents); // 42
|
|
684
|
+
* ```
|
|
685
|
+
*/
|
|
686
|
+
fromBuffer(targetBuf: Buffer): PointerInstance;
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Create a pointer from a raw memory address.
|
|
690
|
+
*
|
|
691
|
+
* Use this to create typed access to native memory, especially useful with
|
|
692
|
+
* `c_void_p` struct fields that point to arrays of structs.
|
|
693
|
+
*
|
|
694
|
+
* @param address - Memory address as BigInt or number
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* ```javascript
|
|
698
|
+
* // Access array of structs from a c_void_p field
|
|
699
|
+
* const pValues = POINTER(ADSVALUE).fromAddress(col.pADsValues);
|
|
700
|
+
* for (let i = 0; i < col.dwNumValues; i++) {
|
|
701
|
+
* console.log(pValues[i].dwType);
|
|
702
|
+
* }
|
|
703
|
+
* ```
|
|
704
|
+
*/
|
|
705
|
+
fromAddress(address: bigint | number): PointerInstance;
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* @deprecated Use pointer instance `.contents` instead.
|
|
709
|
+
* Legacy API: Dereferences a pointer buffer.
|
|
710
|
+
*/
|
|
572
711
|
deref(ptrBuf: Buffer): bigint | null;
|
|
573
|
-
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* @deprecated Use pointer instance `.set()` instead.
|
|
715
|
+
* Legacy API: Sets pointer buffer value.
|
|
716
|
+
*/
|
|
574
717
|
set(ptrBuf: Buffer, value: Buffer | bigint): void;
|
|
718
|
+
|
|
575
719
|
toString(): string;
|
|
576
720
|
}
|
|
577
721
|
|
|
@@ -943,6 +1087,22 @@ export function writeValue(ptr: Buffer | bigint | number, type: AnyType, value:
|
|
|
943
1087
|
*/
|
|
944
1088
|
export function sizeof(type: AnyType | StructDef | ArrayTypeDef): number;
|
|
945
1089
|
|
|
1090
|
+
/**
|
|
1091
|
+
* Get the alignment requirement of a type in bytes.
|
|
1092
|
+
*
|
|
1093
|
+
* Python equivalent: `ctypes.alignment`
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```javascript
|
|
1097
|
+
* alignment(c_int32) // 4
|
|
1098
|
+
* alignment(c_double) // 8
|
|
1099
|
+
* alignment(MyStruct) // max field alignment
|
|
1100
|
+
* ```
|
|
1101
|
+
*
|
|
1102
|
+
* @category Memory
|
|
1103
|
+
*/
|
|
1104
|
+
export function alignment(type: AnyType | StructDef | ArrayTypeDef | typeof Structure | typeof Union): number;
|
|
1105
|
+
|
|
946
1106
|
/**
|
|
947
1107
|
* Create a Buffer view of native memory at a given address.
|
|
948
1108
|
*
|
|
@@ -1059,12 +1219,31 @@ export function byref(obj: Buffer | SimpleCDataInstance | { _buffer: Buffer }):
|
|
|
1059
1219
|
*
|
|
1060
1220
|
* Python equivalent: `ctypes.cast`
|
|
1061
1221
|
*
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1222
|
+
* When the target is a {@link PointerTypeDef}, returns a {@link PointerInstance} with
|
|
1223
|
+
* `.contents` and `[index]` access — equivalent to Python's
|
|
1224
|
+
* `cast(c_void_p(addr), POINTER(MyStruct))`.
|
|
1225
|
+
*
|
|
1226
|
+
* @param ptr - Buffer, BigInt address, number, or SimpleCData instance (e.g., `c_void_p`)
|
|
1227
|
+
* @param targetType - The target type (primitive, struct, or POINTER type)
|
|
1228
|
+
*
|
|
1229
|
+
* @example Cast to POINTER for typed array access
|
|
1230
|
+
* ```javascript
|
|
1231
|
+
* // Python: cast(c_void_p(addr), POINTER(MyStruct))
|
|
1232
|
+
* const pValues = cast(col.pADsValues, POINTER(ADSVALUE));
|
|
1233
|
+
* for (let i = 0; i < col.dwNumValues; i++) {
|
|
1234
|
+
* console.log(pValues[i].dwType);
|
|
1235
|
+
* }
|
|
1236
|
+
* ```
|
|
1237
|
+
*
|
|
1238
|
+
* @example Cast to primitive type
|
|
1239
|
+
* ```javascript
|
|
1240
|
+
* const floatVal = cast(intBuf, c_float);
|
|
1241
|
+
* ```
|
|
1064
1242
|
*
|
|
1065
1243
|
* @category Pointers
|
|
1066
1244
|
*/
|
|
1067
|
-
export function cast(ptr: Buffer | bigint
|
|
1245
|
+
export function cast(ptr: Buffer | bigint | number | SimpleCDataInstance, targetType: PointerTypeDef): PointerInstance;
|
|
1246
|
+
export function cast(ptr: Buffer | bigint | number | SimpleCDataInstance, targetType: AnyType | StructDef): any;
|
|
1068
1247
|
|
|
1069
1248
|
/**
|
|
1070
1249
|
* Create a pointer type for a given base type.
|
|
@@ -1074,7 +1253,7 @@ export function cast(ptr: Buffer | bigint, targetType: AnyType | StructDef): Buf
|
|
|
1074
1253
|
* @param baseType - The type to point to
|
|
1075
1254
|
* @returns A pointer type with `create()`, `fromBuffer()`, etc.
|
|
1076
1255
|
*
|
|
1077
|
-
* @example
|
|
1256
|
+
* @example Basic pointer
|
|
1078
1257
|
* ```javascript
|
|
1079
1258
|
* const IntPtr = POINTER(c_int32);
|
|
1080
1259
|
* const buf = Buffer.alloc(4);
|
|
@@ -1082,7 +1261,20 @@ export function cast(ptr: Buffer | bigint, targetType: AnyType | StructDef): Buf
|
|
|
1082
1261
|
*
|
|
1083
1262
|
* const p = IntPtr.fromBuffer(buf);
|
|
1084
1263
|
* console.log(p.contents); // 42
|
|
1085
|
-
* console.log(p[0]);
|
|
1264
|
+
* console.log(p[0]); // 42
|
|
1265
|
+
* ```
|
|
1266
|
+
*
|
|
1267
|
+
* @example Typed access to native array via c_void_p struct field
|
|
1268
|
+
* ```javascript
|
|
1269
|
+
* // Structure fields don't accept POINTER() types directly — use c_void_p,
|
|
1270
|
+
* // then wrap with POINTER().fromAddress() for typed indexed access:
|
|
1271
|
+
* class Column extends Structure {
|
|
1272
|
+
* static _fields_ = [["pValues", c_void_p], ["count", c_uint32]];
|
|
1273
|
+
* }
|
|
1274
|
+
* const pValues = POINTER(ValueStruct).fromAddress(col.pValues);
|
|
1275
|
+
* for (let i = 0; i < col.count; i++) {
|
|
1276
|
+
* console.log(pValues[i].field); // struct view at offset i
|
|
1277
|
+
* }
|
|
1086
1278
|
* ```
|
|
1087
1279
|
*
|
|
1088
1280
|
* @category Pointers
|
|
@@ -1108,7 +1300,7 @@ export function POINTER(baseType: AnyType | StructDef): PointerTypeDef;
|
|
|
1108
1300
|
*
|
|
1109
1301
|
* @category Pointers
|
|
1110
1302
|
*/
|
|
1111
|
-
export function pointer(obj: SimpleCDataInstance | { _buffer: Buffer }):
|
|
1303
|
+
export function pointer(obj: SimpleCDataInstance | { _buffer: Buffer }): PointerInstance;
|
|
1112
1304
|
|
|
1113
1305
|
/**
|
|
1114
1306
|
* Get the C library errno value.
|
|
@@ -1264,8 +1456,10 @@ export const c_wchar_p: SimpleCDataConstructor;
|
|
|
1264
1456
|
export const c_void_p: SimpleCDataConstructor;
|
|
1265
1457
|
/** Boolean (1 byte). Python: `ctypes.c_bool` @category Types */
|
|
1266
1458
|
export const c_bool: SimpleCDataConstructor;
|
|
1267
|
-
/** Platform-dependent size type (BigInt). Python: `ctypes.c_size_t` @category Types */
|
|
1459
|
+
/** Platform-dependent unsigned size type (BigInt). Python: `ctypes.c_size_t` @category Types */
|
|
1268
1460
|
export const c_size_t: SimpleCDataConstructor;
|
|
1461
|
+
/** Platform-dependent signed size type (BigInt). Python: `ctypes.c_ssize_t` @category Types */
|
|
1462
|
+
export const c_ssize_t: SimpleCDataConstructor;
|
|
1269
1463
|
/** Platform-dependent signed long. Python: `ctypes.c_long` @category Types */
|
|
1270
1464
|
export const c_long: SimpleCDataConstructor;
|
|
1271
1465
|
/** Platform-dependent unsigned long. Python: `ctypes.c_ulong` @category Types */
|
package/lib/index.js
CHANGED
|
@@ -207,6 +207,36 @@ function sizeof(type) {
|
|
|
207
207
|
return _sizeof(type, Structure, Union);
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
function alignment(type) {
|
|
211
|
+
// Instance of Structure/Union — use _structDef/_unionDef (Python: alignment(instance) works)
|
|
212
|
+
if (type instanceof Structure || type instanceof Union) {
|
|
213
|
+
const def = type._structDef || type._unionDef;
|
|
214
|
+
return def ? def.alignment : 1;
|
|
215
|
+
}
|
|
216
|
+
// SimpleCData instance — delegate to class (Python: alignment(c_int32(42)) works)
|
|
217
|
+
if (typeof type === "object" && type !== null && type.constructor && type.constructor._isSimpleCData) {
|
|
218
|
+
return alignment(type.constructor);
|
|
219
|
+
}
|
|
220
|
+
// Structure/Union class
|
|
221
|
+
if (typeof type === "function" && (type.prototype instanceof Structure || type.prototype instanceof Union)) {
|
|
222
|
+
const def = type._structDef || type._unionDef || type._buildStruct?.() || type._buildUnion?.();
|
|
223
|
+
return def ? def.alignment : 1;
|
|
224
|
+
}
|
|
225
|
+
// StructDef / UnionDef object
|
|
226
|
+
if (typeof type === "object" && type !== null && type._isStructType && type.alignment !== undefined) {
|
|
227
|
+
return type.alignment;
|
|
228
|
+
}
|
|
229
|
+
// ArrayTypeDef
|
|
230
|
+
if (typeof type === "object" && type !== null && type._isArrayType) {
|
|
231
|
+
return type.getAlignment();
|
|
232
|
+
}
|
|
233
|
+
// SimpleCData class — natural alignment = min(size, POINTER_SIZE)
|
|
234
|
+
if (typeof type === "function" && type._isSimpleCData) {
|
|
235
|
+
return Math.min(type._size, native.POINTER_SIZE);
|
|
236
|
+
}
|
|
237
|
+
throw new TypeError("alignment() argument must be a ctypes type");
|
|
238
|
+
}
|
|
239
|
+
|
|
210
240
|
// ============================================================================
|
|
211
241
|
// Pointer Operations
|
|
212
242
|
// Now imported from ./memory/pointer.js - see that file for implementation details
|
|
@@ -221,7 +251,7 @@ function byref(obj) {
|
|
|
221
251
|
}
|
|
222
252
|
|
|
223
253
|
function cast(ptr, targetType) {
|
|
224
|
-
return _cast(ptr, targetType, readValue, sizeof, ptrToBuffer);
|
|
254
|
+
return _cast(ptr, targetType, readValue, sizeof, ptrToBuffer, native);
|
|
225
255
|
}
|
|
226
256
|
|
|
227
257
|
function ptrToBuffer(address, size) {
|
|
@@ -425,6 +455,7 @@ const {
|
|
|
425
455
|
c_char_p,
|
|
426
456
|
c_wchar_p,
|
|
427
457
|
c_size_t,
|
|
458
|
+
c_ssize_t,
|
|
428
459
|
c_long,
|
|
429
460
|
c_ulong,
|
|
430
461
|
c_byte,
|
|
@@ -505,6 +536,7 @@ export {
|
|
|
505
536
|
readValue,
|
|
506
537
|
writeValue,
|
|
507
538
|
sizeof,
|
|
539
|
+
alignment,
|
|
508
540
|
ptrToBuffer,
|
|
509
541
|
|
|
510
542
|
// Strutture
|
|
@@ -560,6 +592,7 @@ export {
|
|
|
560
592
|
c_void_p,
|
|
561
593
|
c_bool,
|
|
562
594
|
c_size_t,
|
|
595
|
+
c_ssize_t,
|
|
563
596
|
c_long,
|
|
564
597
|
c_ulong,
|
|
565
598
|
// Python-compatible aliases
|
package/lib/memory/operations.js
CHANGED
|
@@ -119,6 +119,12 @@ export function readValue(ptr, type, offset = 0, sizeof, ptrToBuffer, Structure,
|
|
|
119
119
|
return def.toObject(tempBuf);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
// Struct/Union def object (has _isStructType and toObject)
|
|
123
|
+
if (typeof type === "object" && type !== null && type._isStructType && typeof type.toObject === "function") {
|
|
124
|
+
const tempBuf = ptr.subarray(offset, offset + type.size);
|
|
125
|
+
return type.toObject(tempBuf);
|
|
126
|
+
}
|
|
127
|
+
|
|
122
128
|
throw new TypeError(`readValue: unsupported type ${type}`);
|
|
123
129
|
}
|
|
124
130
|
|
|
@@ -211,6 +217,19 @@ export function writeValue(ptr, type, value, offset = 0, sizeof, Structure, Unio
|
|
|
211
217
|
return def.size;
|
|
212
218
|
}
|
|
213
219
|
|
|
220
|
+
// Struct/Union def object (has _isStructType and set/fromObject)
|
|
221
|
+
if (typeof type === "object" && type !== null && type._isStructType && typeof type.set === "function") {
|
|
222
|
+
const tempBuf = ptr.subarray(offset, offset + type.size);
|
|
223
|
+
if (Buffer.isBuffer(value)) {
|
|
224
|
+
value.copy(tempBuf, 0, 0, type.size);
|
|
225
|
+
} else if (typeof value === "object" && value !== null) {
|
|
226
|
+
for (const [k, v] of Object.entries(value)) {
|
|
227
|
+
type.set(tempBuf, k, v);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return type.size;
|
|
231
|
+
}
|
|
232
|
+
|
|
214
233
|
throw new TypeError(`writeValue: unsupported type ${type}`);
|
|
215
234
|
}
|
|
216
235
|
|
package/lib/memory/pointer.js
CHANGED
|
@@ -53,6 +53,10 @@
|
|
|
53
53
|
* ```
|
|
54
54
|
*/
|
|
55
55
|
export function addressOf(ptr, alloc, native) {
|
|
56
|
+
// If it's an object with _buffer (SimpleCData, Structure, Union, array proxy), use its buffer
|
|
57
|
+
if (!Buffer.isBuffer(ptr) && ptr && ptr._buffer && Buffer.isBuffer(ptr._buffer)) {
|
|
58
|
+
ptr = ptr._buffer;
|
|
59
|
+
}
|
|
56
60
|
if (Buffer.isBuffer(ptr)) {
|
|
57
61
|
// Get the buffer's memory address
|
|
58
62
|
const tempBuf = alloc(native.POINTER_SIZE);
|
|
@@ -164,7 +168,7 @@ export function byref(obj) {
|
|
|
164
168
|
* console.log(header.contents); // { magic: 23117, version: 1 }
|
|
165
169
|
* ```
|
|
166
170
|
*/
|
|
167
|
-
export function cast(ptr, targetType, readValue, sizeof, ptrToBuffer) {
|
|
171
|
+
export function cast(ptr, targetType, readValue, sizeof, ptrToBuffer, native) {
|
|
168
172
|
// Validate inputs
|
|
169
173
|
if (!ptr) {
|
|
170
174
|
throw new TypeError("cast() requires a non-null pointer");
|
|
@@ -173,6 +177,62 @@ export function cast(ptr, targetType, readValue, sizeof, ptrToBuffer) {
|
|
|
173
177
|
throw new TypeError("cast() requires a target type");
|
|
174
178
|
}
|
|
175
179
|
|
|
180
|
+
// PointerTypeDef — return a PointerInstance via fromAddress() or fromBuffer()
|
|
181
|
+
// Python equivalent: cast(c_void_p(addr), POINTER(c_int32)) — read stored address
|
|
182
|
+
// Python equivalent: cast(arr, POINTER(c_int32)) — pointer to arr's memory
|
|
183
|
+
// Python equivalent: cast(p, POINTER(c_double)) — pointer to same memory as p
|
|
184
|
+
if (typeof targetType === "object" && targetType._pointerTo !== undefined) {
|
|
185
|
+
// PointerInstance — use its address/buffer (Python: cast(p, POINTER(OtherType)))
|
|
186
|
+
if (ptr && typeof ptr === "object" && typeof ptr.address === "bigint") {
|
|
187
|
+
if (ptr._buffer) {
|
|
188
|
+
return targetType.fromBuffer(ptr._buffer);
|
|
189
|
+
}
|
|
190
|
+
return targetType.fromAddress(ptr.address);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ctypes object with _buffer — distinguish data objects from pointer-value objects
|
|
194
|
+
// Note: array proxies are Buffer.isBuffer()==true but also have ._buffer, so don't exclude Buffers
|
|
195
|
+
if (ptr && typeof ptr === "object" && ptr._buffer && Buffer.isBuffer(ptr._buffer)) {
|
|
196
|
+
// SimpleCData storing a pointer/address value (c_void_p, c_char_p, etc.)
|
|
197
|
+
// → read the stored address value from the buffer
|
|
198
|
+
if (ptr.constructor && ptr.constructor._isSimpleCData && ptr.constructor._type === native.CType.POINTER) {
|
|
199
|
+
// This is a pointer-valued SimpleCData — read address from buffer
|
|
200
|
+
const buf = ptr._buffer;
|
|
201
|
+
let addr;
|
|
202
|
+
if (buf.length >= 8) {
|
|
203
|
+
addr = buf.readBigUInt64LE(0);
|
|
204
|
+
} else if (buf.length >= 4) {
|
|
205
|
+
addr = BigInt(buf.readUInt32LE(0));
|
|
206
|
+
} else {
|
|
207
|
+
throw new TypeError("cast(): buffer too small to contain a pointer");
|
|
208
|
+
}
|
|
209
|
+
return targetType.fromAddress(addr);
|
|
210
|
+
}
|
|
211
|
+
// Array, Structure, Union — pointer to their data buffer
|
|
212
|
+
// Python: cast(arr, POINTER(c_int32)) points to arr's memory
|
|
213
|
+
return targetType.fromBuffer(ptr._buffer);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let addr;
|
|
217
|
+
if (typeof ptr === "bigint") {
|
|
218
|
+
addr = ptr;
|
|
219
|
+
} else if (typeof ptr === "number") {
|
|
220
|
+
addr = BigInt(ptr);
|
|
221
|
+
} else if (Buffer.isBuffer(ptr)) {
|
|
222
|
+
// Read the pointer value from the buffer
|
|
223
|
+
if (ptr.length >= 8) {
|
|
224
|
+
addr = ptr.readBigUInt64LE(0);
|
|
225
|
+
} else if (ptr.length >= 4) {
|
|
226
|
+
addr = BigInt(ptr.readUInt32LE(0));
|
|
227
|
+
} else {
|
|
228
|
+
throw new TypeError("cast(): buffer too small to contain a pointer");
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
throw new TypeError("cast(): ptr must be a BigInt, number, Buffer, ctypes instance, or PointerInstance");
|
|
232
|
+
}
|
|
233
|
+
return targetType.fromAddress(addr);
|
|
234
|
+
}
|
|
235
|
+
|
|
176
236
|
// Struct type - return wrapper object
|
|
177
237
|
if (typeof targetType === "object" && targetType.size !== undefined) {
|
|
178
238
|
const buf = Buffer.isBuffer(ptr) ? ptr : ptrToBuffer(ptr, targetType.size);
|
|
@@ -287,7 +347,7 @@ export function ptrToBuffer(address, size, native) {
|
|
|
287
347
|
*/
|
|
288
348
|
export function POINTER(baseType, sizeof, alloc, readValue, writeValue, c_void_p, native) {
|
|
289
349
|
const baseSize = typeof baseType === "object" ? baseType.size : sizeof(baseType);
|
|
290
|
-
const typeName = typeof baseType === "object" ? "struct" : baseType._type || "unknown";
|
|
350
|
+
const typeName = typeof baseType === "object" ? "struct" : baseType._type || baseType.name || "unknown";
|
|
291
351
|
|
|
292
352
|
/**
|
|
293
353
|
* Helper to get buffer's memory address using native writeValue
|
|
@@ -558,13 +618,16 @@ export function pointer(obj, POINTER_fn, sizeof, alloc, readValue, writeValue, c
|
|
|
558
618
|
} else if (obj && obj._buffer) {
|
|
559
619
|
// Structure/Union instance or SimpleCData with _buffer
|
|
560
620
|
targetBuffer = obj._buffer;
|
|
561
|
-
// Get the base type
|
|
621
|
+
// Get the base type for POINTER creation
|
|
562
622
|
if (obj.constructor && obj.constructor._type) {
|
|
563
|
-
// SimpleCData instance - use the class itself
|
|
623
|
+
// SimpleCData instance - use the class itself (c_int32, c_double, etc.)
|
|
564
624
|
baseType = obj.constructor;
|
|
625
|
+
} else if (obj._structDef) {
|
|
626
|
+
// Structure/Union instance - use the struct def object
|
|
627
|
+
// (obj.constructor is a bound function from Proxy, so we use _structDef directly)
|
|
628
|
+
baseType = obj._structDef;
|
|
565
629
|
} else {
|
|
566
|
-
|
|
567
|
-
baseType = obj._structDef || obj.__structDef || c_void_p;
|
|
630
|
+
baseType = c_void_p;
|
|
568
631
|
}
|
|
569
632
|
} else {
|
|
570
633
|
throw new TypeError("pointer() argument must be a ctypes instance or Buffer");
|
|
@@ -307,6 +307,34 @@ export function struct(fields, options = {}, sizeof, alloc, readValue, writeValu
|
|
|
307
307
|
maxAlignment = alignment;
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
+
// Caso 4b: POINTER() type — stored as pointer-sized field with typed access
|
|
311
|
+
else if (typeof type === "object" && type !== null && type._pointerTo !== undefined) {
|
|
312
|
+
// Reset bit field state
|
|
313
|
+
currentBitFieldBase = null;
|
|
314
|
+
currentBitOffset = 0;
|
|
315
|
+
|
|
316
|
+
const size = native.POINTER_SIZE;
|
|
317
|
+
const alignment = packed ? 1 : Math.min(size, native.POINTER_SIZE);
|
|
318
|
+
|
|
319
|
+
if (!packed && totalSize % alignment !== 0) {
|
|
320
|
+
totalSize += alignment - (totalSize % alignment);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
fieldDef = {
|
|
324
|
+
name,
|
|
325
|
+
type,
|
|
326
|
+
offset: totalSize,
|
|
327
|
+
size,
|
|
328
|
+
alignment,
|
|
329
|
+
isPointer: true,
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
totalSize += size;
|
|
333
|
+
|
|
334
|
+
if (alignment > maxAlignment) {
|
|
335
|
+
maxAlignment = alignment;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
310
338
|
// Caso 4: Tipo base (SimpleCData)
|
|
311
339
|
else {
|
|
312
340
|
// Reset bit field state
|
|
@@ -369,6 +397,37 @@ export function struct(fields, options = {}, sizeof, alloc, readValue, writeValu
|
|
|
369
397
|
continue;
|
|
370
398
|
}
|
|
371
399
|
|
|
400
|
+
// POINTER() type field — read returns PointerInstance, write accepts BigInt/PointerInstance
|
|
401
|
+
if (field.isPointer) {
|
|
402
|
+
const fieldOffset = offset;
|
|
403
|
+
const ptrType = field.type;
|
|
404
|
+
fieldReaders.set(name, (buf) => {
|
|
405
|
+
const addr = native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(fieldOffset) : BigInt(buf.readUInt32LE(fieldOffset));
|
|
406
|
+
return ptrType.fromAddress(addr);
|
|
407
|
+
});
|
|
408
|
+
fieldWriters.set(name, (buf, val) => {
|
|
409
|
+
let addr;
|
|
410
|
+
if (typeof val === "bigint") {
|
|
411
|
+
addr = val;
|
|
412
|
+
} else if (typeof val === "number") {
|
|
413
|
+
addr = BigInt(val);
|
|
414
|
+
} else if (val && typeof val.address === "bigint") {
|
|
415
|
+
// PointerInstance
|
|
416
|
+
addr = val.address;
|
|
417
|
+
} else if (Buffer.isBuffer(val)) {
|
|
418
|
+
addr = native.POINTER_SIZE === 8 ? val.readBigUInt64LE(0) : BigInt(val.readUInt32LE(0));
|
|
419
|
+
} else {
|
|
420
|
+
addr = 0n;
|
|
421
|
+
}
|
|
422
|
+
if (native.POINTER_SIZE === 8) {
|
|
423
|
+
buf.writeBigUInt64LE(addr, fieldOffset);
|
|
424
|
+
} else {
|
|
425
|
+
buf.writeUInt32LE(Number(addr), fieldOffset);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
|
|
372
431
|
// Pre-compile based on SimpleCData type
|
|
373
432
|
// Use the type's _reader and _writer directly for optimization
|
|
374
433
|
const fieldType = field.type;
|
|
@@ -662,6 +721,12 @@ export function struct(fields, options = {}, sizeof, alloc, readValue, writeValu
|
|
|
662
721
|
: field.type.toObject(nestedBuf);
|
|
663
722
|
}
|
|
664
723
|
|
|
724
|
+
// POINTER() field — return PointerInstance
|
|
725
|
+
if (field.isPointer) {
|
|
726
|
+
const addr = native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(field.offset) : BigInt(buf.readUInt32LE(field.offset));
|
|
727
|
+
return field.type.fromAddress(addr);
|
|
728
|
+
}
|
|
729
|
+
|
|
665
730
|
// Array field
|
|
666
731
|
if (field.isArray) {
|
|
667
732
|
const arrayBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
@@ -748,6 +813,26 @@ export function struct(fields, options = {}, sizeof, alloc, readValue, writeValu
|
|
|
748
813
|
return;
|
|
749
814
|
}
|
|
750
815
|
|
|
816
|
+
// POINTER() field — write address
|
|
817
|
+
if (field.isPointer) {
|
|
818
|
+
let addr;
|
|
819
|
+
if (typeof value === "bigint") {
|
|
820
|
+
addr = value;
|
|
821
|
+
} else if (typeof value === "number") {
|
|
822
|
+
addr = BigInt(value);
|
|
823
|
+
} else if (value && typeof value.address === "bigint") {
|
|
824
|
+
addr = value.address;
|
|
825
|
+
} else {
|
|
826
|
+
addr = 0n;
|
|
827
|
+
}
|
|
828
|
+
if (native.POINTER_SIZE === 8) {
|
|
829
|
+
buf.writeBigUInt64LE(addr, field.offset);
|
|
830
|
+
} else {
|
|
831
|
+
buf.writeUInt32LE(Number(addr), field.offset);
|
|
832
|
+
}
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
|
|
751
836
|
// Array field
|
|
752
837
|
if (field.isArray) {
|
|
753
838
|
if (Buffer.isBuffer(value)) {
|
|
@@ -875,6 +960,9 @@ export function struct(fields, options = {}, sizeof, alloc, readValue, writeValu
|
|
|
875
960
|
} else {
|
|
876
961
|
result[field.name] = nestedObj;
|
|
877
962
|
}
|
|
963
|
+
} else if (field.isPointer) {
|
|
964
|
+
const addr = native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(field.offset) : BigInt(buf.readUInt32LE(field.offset));
|
|
965
|
+
result[field.name] = field.type.fromAddress(addr);
|
|
878
966
|
} else if (field.isArray) {
|
|
879
967
|
const arrayBuf = buf.subarray(field.offset, field.offset + field.size);
|
|
880
968
|
result[field.name] = field.type.wrap(arrayBuf);
|
|
@@ -123,6 +123,13 @@ export function union(fields, sizeof, alloc, readValue, writeValue, _isStruct, _
|
|
|
123
123
|
fieldDef.baseSize = type.baseSize;
|
|
124
124
|
fieldDef.type = type.baseType; // Usa il tipo base per lettura/scrittura
|
|
125
125
|
}
|
|
126
|
+
// POINTER() type
|
|
127
|
+
else if (typeof type === "object" && type !== null && type._pointerTo !== undefined) {
|
|
128
|
+
size = native.POINTER_SIZE;
|
|
129
|
+
alignment = Math.min(size, native.POINTER_SIZE);
|
|
130
|
+
fieldDef.type = type;
|
|
131
|
+
fieldDef.isPointer = true;
|
|
132
|
+
}
|
|
126
133
|
// Tipo base (SimpleCData)
|
|
127
134
|
else {
|
|
128
135
|
// Validate type is a SimpleCData class
|
|
@@ -313,6 +320,12 @@ export function union(fields, sizeof, alloc, readValue, writeValue, _isStruct, _
|
|
|
313
320
|
return field.type.wrap(buf.subarray(field.offset, field.offset + field.size));
|
|
314
321
|
}
|
|
315
322
|
|
|
323
|
+
// POINTER() field — return PointerInstance
|
|
324
|
+
if (field.isPointer) {
|
|
325
|
+
const addr = native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(field.offset) : BigInt(buf.readUInt32LE(field.offset));
|
|
326
|
+
return field.type.fromAddress(addr);
|
|
327
|
+
}
|
|
328
|
+
|
|
316
329
|
// Tipo base
|
|
317
330
|
return readValue(buf, field.type, field.offset);
|
|
318
331
|
},
|
|
@@ -369,6 +382,28 @@ export function union(fields, sizeof, alloc, readValue, writeValue, _isStruct, _
|
|
|
369
382
|
return;
|
|
370
383
|
}
|
|
371
384
|
|
|
385
|
+
// POINTER() field — write address
|
|
386
|
+
if (field.isPointer) {
|
|
387
|
+
let addr;
|
|
388
|
+
if (typeof value === "bigint") {
|
|
389
|
+
addr = value;
|
|
390
|
+
} else if (typeof value === "number") {
|
|
391
|
+
addr = BigInt(value);
|
|
392
|
+
} else if (value && typeof value.address === "bigint") {
|
|
393
|
+
addr = value.address;
|
|
394
|
+
} else if (Buffer.isBuffer(value)) {
|
|
395
|
+
addr = native.POINTER_SIZE === 8 ? value.readBigUInt64LE(0) : BigInt(value.readUInt32LE(0));
|
|
396
|
+
} else {
|
|
397
|
+
addr = 0n;
|
|
398
|
+
}
|
|
399
|
+
if (native.POINTER_SIZE === 8) {
|
|
400
|
+
buf.writeBigUInt64LE(addr, field.offset);
|
|
401
|
+
} else {
|
|
402
|
+
buf.writeUInt32LE(Number(addr), field.offset);
|
|
403
|
+
}
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
372
407
|
// Tipo base
|
|
373
408
|
writeValue(buf, field.type, value, field.offset);
|
|
374
409
|
},
|
|
@@ -422,6 +457,9 @@ export function union(fields, sizeof, alloc, readValue, writeValue, _isStruct, _
|
|
|
422
457
|
} else if (field.isArray) {
|
|
423
458
|
const wrapped = field.type.wrap(buf.subarray(0, field.size));
|
|
424
459
|
return [...wrapped];
|
|
460
|
+
} else if (field.isPointer) {
|
|
461
|
+
const addr = native.POINTER_SIZE === 8 ? buf.readBigUInt64LE(0) : BigInt(buf.readUInt32LE(0));
|
|
462
|
+
return field.type.fromAddress(addr);
|
|
425
463
|
} else {
|
|
426
464
|
return readValue(buf, field.type, 0);
|
|
427
465
|
}
|
|
@@ -429,6 +467,24 @@ export function union(fields, sizeof, alloc, readValue, writeValue, _isStruct, _
|
|
|
429
467
|
set(value) {
|
|
430
468
|
if (field.isBitField) {
|
|
431
469
|
_writeBitField(buf, 0, field.type, field.bitOffset, field.bitSize, value, sizeof);
|
|
470
|
+
} else if (field.isPointer) {
|
|
471
|
+
let addr;
|
|
472
|
+
if (typeof value === "bigint") {
|
|
473
|
+
addr = value;
|
|
474
|
+
} else if (typeof value === "number") {
|
|
475
|
+
addr = BigInt(value);
|
|
476
|
+
} else if (value && typeof value.address === "bigint") {
|
|
477
|
+
addr = value.address;
|
|
478
|
+
} else if (Buffer.isBuffer(value)) {
|
|
479
|
+
addr = native.POINTER_SIZE === 8 ? value.readBigUInt64LE(0) : BigInt(value.readUInt32LE(0));
|
|
480
|
+
} else {
|
|
481
|
+
addr = 0n;
|
|
482
|
+
}
|
|
483
|
+
if (native.POINTER_SIZE === 8) {
|
|
484
|
+
buf.writeBigUInt64LE(addr, 0);
|
|
485
|
+
} else {
|
|
486
|
+
buf.writeUInt32LE(Number(addr), 0);
|
|
487
|
+
}
|
|
432
488
|
} else {
|
|
433
489
|
writeValue(buf, field.type, value, 0);
|
|
434
490
|
}
|
package/lib/types/primitives.js
CHANGED
|
@@ -284,6 +284,21 @@ export function createPrimitiveTypes(SimpleCData, native, addressOf, cstring, ws
|
|
|
284
284
|
};
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
class c_ssize_t extends SimpleCData {
|
|
288
|
+
static _size = native.POINTER_SIZE;
|
|
289
|
+
static _type = CType.SSIZE_T;
|
|
290
|
+
static _reader = (buf, off) => {
|
|
291
|
+
return native.POINTER_SIZE === 8 ? buf.readBigInt64LE(off) : buf.readInt32LE(off);
|
|
292
|
+
};
|
|
293
|
+
static _writer = (buf, off, val) => {
|
|
294
|
+
if (native.POINTER_SIZE === 8) {
|
|
295
|
+
buf.writeBigInt64LE(BigInt(val), off);
|
|
296
|
+
} else {
|
|
297
|
+
buf.writeInt32LE(Number(val), off);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
287
302
|
// Get actual long size from native module (4 on Windows, 4 or 8 on Unix depending on arch)
|
|
288
303
|
const _longSize = native.sizeof ? native.sizeof(CType.LONG) : 4;
|
|
289
304
|
|
|
@@ -408,6 +423,7 @@ export function createPrimitiveTypes(SimpleCData, native, addressOf, cstring, ws
|
|
|
408
423
|
c_wchar_p,
|
|
409
424
|
// Platform-specific
|
|
410
425
|
c_size_t,
|
|
426
|
+
c_ssize_t,
|
|
411
427
|
c_long,
|
|
412
428
|
c_ulong,
|
|
413
429
|
// Python-compatible aliases
|